From ac3664d151e6d4c9704180df1d01c2ed1dedb49d Mon Sep 17 00:00:00 2001 From: Alonso Rodriguez Date: Thu, 25 May 2023 18:50:55 +0200 Subject: [PATCH] Merge develop into main (#2126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump github.com/urfave/cli/v2 from 2.24.3 to 2.24.4 (#1670) Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.3 to 2.24.4. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.3...v2.24.4) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/rubenv/sql-migrate (#1694) Bumps [github.com/rubenv/sql-migrate](https://github.com/rubenv/sql-migrate) from 0.0.0-20211023115951-9f02b1e13857 to 1.3.1. - [Release notes](https://github.com/rubenv/sql-migrate/releases) - [Commits](https://github.com/rubenv/sql-migrate/commits/v1.3.1) --- updated-dependencies: - dependency-name: github.com/rubenv/sql-migrate dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * get nonce from state (#1710) * get nonce from state * foce block number * foce block number and nonce * build(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#1713) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/common from 0.40.0 to 0.41.0 (#1716) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.40.0 to 0.41.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.40.0...v0.41.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test: adding e2e forced batches test. Signed-off-by: Nikolay Nedkov * test: adding check if the forced batch is also being consolidated/verified. Signed-off-by: Nikolay Nedkov * fix: lint errors and unit tests Signed-off-by: Nikolay Nedkov * new public data (#1719) * fix pool add tx (#1721) * fix pool add tx * fix * fix mining reverted txs (#1712) * add e2e tests to validate reverted txs * fix unsigned tx error handling and test * fix test ip * finish test * finish test * fix reverted errors when calling eth_call * commenting test reverting on constructor * fix jsonrpc tests error handling * fix state unit tests prover url * fix state revert tests --------- Co-authored-by: ToniRamirezM * sequencer fixes (#1724) * sequencer fixes * comment test * fix test * remove default fork id (#1728) * fix (#1727) * fix * remove maxSequenceSize * linter * fix forkID (#1729) * fix forkID * linter * fix test * fix error handling in sequencer (#1730) * fix error handling in sequencer * fix error log * fix error log * fix error log * fix test * fix test * fix (#1735) * add check stateroot in reprocessfull (#1739) * fix stateroot on first run (#1740) * fix stateroot on first run * add check stateroot in reprocessfull * fix * Feature/release run docs (#1725) * Update running prod docs, and public testnet config * update gopackr * update gopackr, without go mod tidy * fix tests (#1733) * fix tests * fix: fixing unit tests. Signed-off-by: Nikolay Nedkov * fix: configs Signed-off-by: Nikolay Nedkov --------- Signed-off-by: Nikolay Nedkov Co-authored-by: Nikolay Nedkov * build(deps): bump golang.org/x/crypto from 0.6.0 to 0.7.0 (#1751) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * allow reverted tx to be added to the pool (#1744) * build(deps): bump github.com/urfave/cli/v2 from 2.24.4 to 2.25.0 (#1750) Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.24.4 to 2.25.0. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.24.4...v2.25.0) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/go-git/go-git/v5 from 5.4.2 to 5.6.0 (#1714) * build(deps): bump github.com/go-git/go-git/v5 from 5.4.2 to 5.6.0 Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.4.2 to 5.6.0. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.4.2...v5.6.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * remove deprecated code --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: tclemos * Fix/reorg pool (#1756) * fix * fix check if reorg * fix finalizer test * New executor error: Balance Mismatch (#1720) * new executor error * fix test * build(deps): bump github.com/spf13/afero from 1.9.4 to 1.9.5 (#1757) Bumps [github.com/spf13/afero](https://github.com/spf13/afero) from 1.9.4 to 1.9.5. - [Release notes](https://github.com/spf13/afero/releases) - [Commits](https://github.com/spf13/afero/compare/v1.9.4...v1.9.5) --- updated-dependencies: - dependency-name: github.com/spf13/afero dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Broadcast URI (#1722) * Broadcast URI * fix synchronizer test * fix * check if reorg in sequencer * JRPC - debug methods review (#1650) * Fix revert message for sc deployment tx reverted on the constructor (#1737) * Change %w to %v in logs (#1764) * build(deps): bump github.com/rubenv/sql-migrate from 1.3.1 to 1.4.0 (#1769) Bumps [github.com/rubenv/sql-migrate](https://github.com/rubenv/sql-migrate) from 1.3.1 to 1.4.0. - [Release notes](https://github.com/rubenv/sql-migrate/releases) - [Commits](https://github.com/rubenv/sql-migrate/compare/v1.3.1...v1.4.0) --- updated-dependencies: - dependency-name: github.com/rubenv/sql-migrate dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Aggregator] More fine-grained logs in case of prover errors (#1718) Closes #1717. This PR adds logs in case of errors happening in the methods responsible to interact with the prover for proof generation. This additional logs are necessary in order to print more information, in particular, the `proofId` and `batches` (or `batch`) fields, which is not available in the outer scope (the `Channel` method) where the main error log is printed. * Fix formatting in error logs (#1768) Closes #1766 . This PR adds an additional formatting to the error message template, to hold the additional argument that is appended for the stacktrace. This applies to `Errorf` and `Fatalf`. Also the first argument of the 'w' functions (`Infow`, `Debugw`, ...) has been renamed `msg`, the previous `template` name was misleading because actually it is not treated as a template. * Expire transactions (#1765) * expire too old txs in the efficiency list * refactor and new pool retrieval interval config parameter * reimplement * fix pool retrieval * fix config test * fix config test * update prover image (#1772) * Fix/reorg (#1771) * sequencer logs * logs * fix pool tx * fixes * fix + log * fix if * fix * Remove death code * fix * more logs * logs * log * log * log * remove not null for field topic0 * fix topic0 * full response log * remove some logs * linter * comment forced batches test --------- Co-authored-by: Arnau Co-authored-by: ToniRamirezM * add json rpc endpoints doc (#1738) * build(deps): bump google.golang.org/protobuf from 1.28.1 to 1.29.0 (#1775) Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.28.1 to 1.29.0. - [Release notes](https://github.com/protocolbuffers/protobuf-go/releases) - [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash) - [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.28.1...v1.29.0) --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/common from 0.41.0 to 0.42.0 (#1774) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.41.0 to 0.42.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/iden3/go-iden3-crypto (#1773) Bumps [github.com/iden3/go-iden3-crypto](https://github.com/iden3/go-iden3-crypto) from 0.0.14-0.20220413123345-edc36bfa5247 to 0.0.14. - [Release notes](https://github.com/iden3/go-iden3-crypto/releases) - [Commits](https://github.com/iden3/go-iden3-crypto/commits/v0.0.14) --- updated-dependencies: - dependency-name: github.com/iden3/go-iden3-crypto dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix log (#1777) * fix claim pre execution (#1786) * fix claim pre execution * fix * re fix * re fix * offset (#1788) * Fix/run doc (#1789) Fix running production doc * add support to jrpc to accept short hashes and addresses strings like 0x00 (#1792) * Add restart policy to main docker-compose (#1797) * refactor deprecated things * log (#1804) * close grpc connection (#1816) * add support to jrpc to accept short hashes and addresses strings like 0x00 (#1802) * add check for not found tx and block for trace endpoints (#1811) * Create sonar-project.properties * Create sonarqube.yml * Log startup info as JSON in production (#1799) This commit changes the format of the startup info to be JSON when the log `Environment` configuration is set to `production`. * build(deps): bump google.golang.org/protobuf from 1.29.0 to 1.29.1 (#1828) Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.0 to 1.29.1. - [Release notes](https://github.com/protocolbuffers/protobuf-go/releases) - [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash) - [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.0...v1.29.1) --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: moving print for storing tx in finalizer. Signed-off-by: Nikolay Nedkov * Relay jRPC methods to TrustedSequencer if pool info is needed (#1767) * Fix boot condition for GER signal being sent (#1837) * Fix boot condition for GER signal being sent * Fix boot condition for GER signal being sent * Fix boot condition for GER signal being sent * Flush state db (#1831) * flush state db * flush state db * update prover image * improve log message * improve: adding additional info for txs moved to not ready (#1829) Signed-off-by: Nikolay Nedkov * ForkID logic for an old batch and fix error handling in execute batch (#1803) * etherman forkID event * ForkID * linter * etherman tests * update forkID * Update forkIdIntervals * fix #1830 * suggestion * Prevent sequencer from getting blocked by sync is trusted state is more advanced than virtual state (#1836) * Fix/unsigned tx state root (#1835) * fix unsigned tx to use the correct l2block state root * remove unused variables and logs * update mocks * fix unit tests * solve conflicts --------- Co-authored-by: ToniRamirezM * Add IP to Pool txs (#1817) * Avoid changes on go.mod (#1841) * fix pool ip (#1842) * safer reorg (#1844) * build(deps): bump github.com/go-git/go-git/v5 from 5.6.0 to 5.6.1 (#1848) Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.6.0 to 5.6.1. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.6.0...v5.6.1) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump google.golang.org/protobuf from 1.29.1 to 1.30.0 (#1849) Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.1 to 1.30.0. - [Release notes](https://github.com/protocolbuffers/protobuf-go/releases) - [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash) - [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.1...v1.30.0) --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * add fault tolerance when failed to get revert message (#1846) * Sync Trusted State via jRPC instead of Broadcast (#1840) * break down jrpc package to share objects * sync trusted state via jRPC instead of broadcast --------- Co-authored-by: ToniRamirezM * New Logs and fix to GER Closing Signal (#1868) * fix log * add closing signals logs * fix new ger signal * fix log * fix and enable test * fix finalizer log * Add logs to follow sequencer flow (#1866) * fix pool migration (#1863) * fix pool migration * fix pool migration * fix pool migration * fix * keep the caller locked if an error happens when processing pending monitored txs (#1865) * Log OOC on reprocess full batch (#1876) * enable uncle tests and fix uncle enpoint parameters (#1861) * Update batchresources.go (#1880) * Halt finalizer in case of full execution error (#1879) * panic if trusted reorg in synchronizer * fix (#1878) * log * logs * fixes * sync test commented * fix finalizer * fix encodeTransaction * fix encodeTransaction --------- Co-authored-by: Alonso * Test/broadcast (#1850) Add test for trusted state consumed through permissionless node * check response before checking internal responses (#1882) * add debug endpoints to docs (#1881) * fix get tx by block hash or number and index (#1877) * Improve E2E test time (#1860) * Update software requirements to Ubuntu 22.04 (#1845) The prover needs Ubuntu 22.04. Since this is run in Docker, the requirement for everything should be 22.04. * Fix/failed tx in pool (#1895) * Ignore TxStatusFailed txs in pool during replacement * Ignore TxStatusFailed txs in pool during replacement * wip Signed-off-by: Nikolay Nedkov * improve: adding config params for MaxTxSize in pool and MaxTxSizeForL1 for sequence sender. Signed-off-by: Nikolay Nedkov * improve: moving more hardcoded values to be config props. And adding unit testing of the 'oversized data error'. Signed-off-by: Nikolay Nedkov * Update prover config (#1898) * Update prover config * Enable multiwrite --------- Co-authored-by: Ubuntu * create group 7 and split e2e json rpc tests (#1897) * feat: adding check gas price of tx to be greater that min gas price and min suggested gas price before adding to pool. Signed-off-by: Nikolay Nedkov * docker contracts update (#1903) * genesis + image * smc v1.0.0-fork.3 * etherman + tests * update genblocknumber * linter * latest prover version * fix test * feat: adding check gas price of tx to be greater that min gas price and min suggested gas price before adding to pool. Signed-off-by: Nikolay Nedkov * Truncate value in follower (#1890) * trucate value in follower * truncate gas price * add check to validate eth_call params (#1885) * improve: renaming 'ErrIntrinsicGasPrice' to 'ErrGasPrice' Signed-off-by: Nikolay Nedkov * build(deps): bump github.com/holiman/uint256 from 1.2.1 to 1.2.2 (#1912) Bumps [github.com/holiman/uint256](https://github.com/holiman/uint256) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/holiman/uint256/releases) - [Commits](https://github.com/holiman/uint256/compare/v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: github.com/holiman/uint256 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Feature/#1833 execute batch (#1834) * avoid execute batch twice * fix make run-rpc * linter * Revert "fix make run-rpc" This reverts commit 1b8bddd1fb40a5ff29f3a4f5c4f71e3f7da604a2. * suggestion * remove log * fix eth_call and eth_estimateGas parameters (#1891) * Log events (#1905) * wip * WIP * log OOG on pool pre execution * log high zkcounters use * fix test * fix test * fix test * fix if * fix test * fix test * build(deps): bump google.golang.org/grpc from 1.53.0 to 1.54.0 (#1901) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.54.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.54.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: tclemos * fix: fixing comments. (#1914) * fix: fixing comments. Signed-off-by: Nikolay Nedkov * improve: improving Signed-off-by: Nikolay Nedkov * fix: adding last fixes. Signed-off-by: Nikolay Nedkov --------- Signed-off-by: Nikolay Nedkov * Flush state db after setting genesis (#1908) * Flush state db after setting genesis * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix test * fix tests * fix log L1 tx too big (#1920) * fix missing return on ProcessUnsignedTransaction (#1917) * fix missing return on ProcessUnsignedTransaction * refactor * fix unsigned tx revert response * fix unit tests * fix ProcessBatch err check before reading gas used --------- Co-authored-by: tclemos * Reprocess empty batch to update state root before sanity check (full batch) (#1921) * fix: removing check for low gas price for claims. Signed-off-by: Nikolay Nedkov * fix: removing check for low gas price for claims. (#1922) Signed-off-by: Nikolay Nedkov * improve,test: adding test case for skipping gas price error if tx is claim. Signed-off-by: Nikolay Nedkov * fix forkID (#1925) * fix forkID * fix test * update docker prover forkid 4 + pql cfg improvements (#1929) * update docker prover forkid 4 + pql cfg improvements * increase dbNumberOfPoolConnections * increase dbNumberOfPoolConnections again * update license * build(deps): bump github.com/urfave/cli/v2 from 2.25.0 to 2.25.1 (#1931) Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.0 to 2.25.1. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.25.0...v2.25.1) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Prepare docs and action for mainnet release (#1928) * Adds mainnet config (#1941) * Fix mainnet config * Fix mainnet config * Add mising postgres config for mainnet * remove history limit, replace fatal to error (#1940) * handle fea2scalar error (#1942) * handle fea2scalar error * handle fea2scalar error * trusted reorg if it is not a trusted sequencer (#1945) * trusted reorg if it is not a trusted sequencer * halt * trustedsequencer url as config param (#1956) * add deposit_counter to pool (#1958) * add EIP-1898 support to eth_call (#1961) * tos32 error handling (#1959) * fix log without topics response (#1970) * add issue templates (#1893) * fix BatchNumberByBlockNumber when batch is not found (#1964) * fix claims (#1977) * review jRPC endpoints doc (#1968) * Update executor with forkID 4 support (#1916) Update executor and smart contracts for testing --------- Co-authored-by: Alonso Co-authored-by: tclemos * Stop release generation for RCs (#1982) * create codeql scanning profile * mainnet and rollup exit roots (#1975) * mainnet and rollup exit roots * linter * fix test e2e * doc * fix: adding support for eip-1898 in JSON-RPC for pending methods. Signed-off-by: Nikolay Nedkov * fix: fixing 'endpoints_eth'.'GetTransactionCount' Signed-off-by: Nikolay Nedkov * fix: parameters and return values of 'getBlockNumByArg' and 'getBlockByArg'. Signed-off-by: Nikolay Nedkov * refactoring * remove javascript from codeql * add combined log to jRPC requests (#1986) * web3_clientVersion returns the node version (#1985) * replace map by sync.Map for jRPC filters (#1984) * add example to OPEN RPC doc for zkevm_getBatchByNumber endpoint (#1983) * event log (#1989) * event log * event log * event log * event log * event log * fix config * reuse code * fix * fix * fix Makefile * remove default config * remove default config * remove default config * remove default config * replace the state debug tx to execute just the tx that needs the trace (#1994) * remove broadcast service (#1988) * allow pool to be blocked (#1899) * improve: storing failed rx reason in db. Signed-off-by: Nikolay Nedkov * fix: regenerating mocks. Signed-off-by: Nikolay Nedkov * improve: adding logs of tx efficiency Signed-off-by: Nikolay Nedkov * fix: adding wait group for goroutines started in 'handleTransactionError' so we can await if needed in tests. And making other db deletions async as well. Signed-off-by: Nikolay Nedkov * build(deps): bump golang.org/x/crypto from 0.7.0 to 0.8.0 (#2001) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Make stateTree and executor optional in the state. (#1995) * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * make executor and statedb optional * fix eventlog * fix test * fix method name * move state SQL queries (#2003) * improve: storing 'batch_resources' and 'closing_reason' in 'state.batch' on closing a batch. Signed-off-by: Nikolay Nedkov * Refactor sequencer state interfaces (#2002) * improve: fixing worker todos. Signed-off-by: Nikolay Nedkov * improve: fixing dbmanager todos. Signed-off-by: Nikolay Nedkov * improve: fixing benchmark test scripts todos * build(deps): bump github.com/prometheus/client_golang (#2015) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.14.0 to 1.15.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.14.0...v1.15.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add more details on the compatibility of eth_call (#2018) * Add more details on the compatibility of eth_call * Mention that effective gas price is not included for receipts * Improve timestamp resolution (#2007) * timestamp resolution * fixes * fixes * fix * fix test * fix test * fix test * fix test * fix test * fix test * fix test * refactor code * refactor * refactor check * fix: fixing comments. Signed-off-by: Nikolay Nedkov * fix: fixing comments. Signed-off-by: Nikolay Nedkov * fix: fixing worker AddTxTracker to return drop error reason. Signed-off-by: Nikolay Nedkov * check trusted state before L1 data (#2022) check trusted state before L1 data to avoid havan incomplete trusted state * improve: adding missing usages of TxStatus metric. Signed-off-by: Nikolay Nedkov * fix: fixing sequencer metrics imports and host and port of event-db in debug config. Signed-off-by: Nikolay Nedkov * Improve GHA (#2031) Remove prover mock and ok-to-test * Merges v0.0.6 into Develop (#2039) * fix eventlog config check * fix build version flags * fix optional trace config; update prover docker image * add callTracer (#2010) * go 1.19 * add callTracer, 4byte, noop and prestate tracers * workaround to fix linter problem related to the ruleguard, more details here: https://github.com/golangci/golangci-lint/issues/3107 * fix eth_estimateGas response for reverted txs * Improve claim checks (#2027) * fix wrong state root when prevlastbatch & lastbatch are empty + restart (#2028) * Update production config for prover * Update prover version * fix conflicts * fix conflicts * fix conflicts * Add ALL PRIVILEGES to prover_user for prover_db.state schema * update linter version --------- Co-authored-by: tclemos Co-authored-by: Thiago Coimbra Lemos Co-authored-by: Alonso Rodriguez Co-authored-by: bros Co-authored-by: agnusmor Co-authored-by: agnusmor <100322135+agnusmor@users.noreply.github.com> Co-authored-by: Thiago Lemos * Feature/split network config (#1999) * Move network related config from config.toml to genesis.json * build(deps): bump github.com/iden3/go-iden3-crypto from 0.0.14 to 0.0.15 (#2050) Bumps [github.com/iden3/go-iden3-crypto](https://github.com/iden3/go-iden3-crypto) from 0.0.14 to 0.0.15. - [Release notes](https://github.com/iden3/go-iden3-crypto/releases) - [Commits](https://github.com/iden3/go-iden3-crypto/compare/v0.0.14...v0.0.15) --- updated-dependencies: - dependency-name: github.com/iden3/go-iden3-crypto dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * wip Signed-off-by: Nikolay Nedkov * Remove claim txs (#2048) * remove claim txs * fix tests * fix tests * fix tests * remove deposit_count * fix query * fix query --------- Co-authored-by: Thiago Lemos * wip#2 Signed-off-by: Nikolay Nedkov * wip #3 Signed-off-by: Nikolay Nedkov * Remove claim txs (#2048) * remove claim txs * fix tests * fix tests * fix tests * remove deposit_count * fix query * fix query --------- Co-authored-by: Thiago Lemos * build(deps): bump github.com/urfave/cli/v2 from 2.25.1 to 2.25.3 (#2063) Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.25.1 to 2.25.3. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.25.1...v2.25.3) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Do not use zkcounters on eth_Call (#2021) * not use zkcounters on eth_Call * fix test * prover image * prover image * prover image * fix default trace values for custom tracers (#2066) * add support to safe and finalized blocks for jRPC block parameters (#2049) * cmd/approve: add new flag to set max-amount (#2030) * build(deps): bump github.com/prometheus/client_golang (#2074) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.0 to 1.15.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.15.0...v1.15.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/client_model from 0.3.0 to 0.4.0 (#2073) Bumps [github.com/prometheus/client_model](https://github.com/prometheus/client_model) from 0.3.0 to 0.4.0. - [Release notes](https://github.com/prometheus/client_model/releases) - [Commits](https://github.com/prometheus/client_model/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_model dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix sync_info table (#2055) * fix * linter * merge set last batch info seen methods --------- Co-authored-by: Thiago Lemos * remove unit suffix from duration config params (#2068) * New sequence sender component (#2051) * new sequence sender * fix config file * fix docker-compose * fix e2e tests * fix e2e tests * fix e2e tests * fix e2e tests * fixes * remove keys fron sequencer * fix sequence sender * remove todo * remove txPool dependency * Merge v0.0.8 into develop (#2077) * wip #4 Signed-off-by: Nikolay Nedkov * fix * build(deps): bump github.com/prometheus/common from 0.42.0 to 0.43.0 (#2081) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.42.0 to 0.43.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.42.0...v0.43.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump google.golang.org/grpc from 1.54.0 to 1.55.0 (#2080) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.54.0 to 1.55.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.54.0...v1.55.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump golang.org/x/sync from 0.1.0 to 0.2.0 (#2079) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.1.0 to 0.2.0. - [Commits](https://github.com/golang/sync/compare/v0.1.0...v0.2.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Toni Ramírez <58293609+ToniRamirezM@users.noreply.github.com> * Fix/deployment (#2076) * fix prover permissions * fix docker compose * fix doc * fix script * reduce interval to search forkID events * verify genesis block number check for full nodes * linter * improve: adding error handling for txs of forced batch Signed-off-by: Nikolay Nedkov * Review jRPC default configuration (#2083) * build(deps): bump golang.org/x/net from 0.9.0 to 0.10.0 (#2084) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.9.0 to 0.10.0. - [Commits](https://github.com/golang/net/compare/v0.9.0...v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#2087) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0. - [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Toni Ramírez <58293609+ToniRamirezM@users.noreply.github.com> * config default values (#2090) * config * unit test * MaxTxBytesSize and MaxTxDataBytesSize * fix decode txs (#2091) * configuration fixes (#2094) * improve: finishing implementation of the vector forced batch tests and updating e2e forced batch test to have 1 forced tx. Signed-off-by: Nikolay Nedkov * Update link to protocol specification * remove error logs when the error is related to the tx (#2096) * fix: fixing forced batches error handling and normal batches transaction level error handling. Signed-off-by: Nikolay Nedkov * rename isBatchProcessed * fix: forced batch rom OOC check. Signed-off-by: Nikolay Nedkov * rename isBatchProcessed * second fix Signed-off-by: Nikolay Nedkov * Refactor state errors (#2105) * refactor state errors * refactor state errors * refactor state errors * refactor state errors * refactor state errors * refactor * fix * function rename * fix wg * fix wg * fix * Fix sequencer error (#2108) * fix error not returned * avoid decoding batchl2data when there are no txs * fix * disable auto release on GHA (#2107) * fix executor error handling (#2109) * build(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#2111) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump github.com/prometheus/common from 0.43.0 to 0.44.0 (#2116) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.43.0 to 0.44.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.43.0...v0.44.0) --- updated-dependencies: - dependency-name: github.com/prometheus/common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix error returned during tx decoding (#2117) * fix timestamp resolution to 10s (#2112) * build(deps): bump github.com/go-git/go-git/v5 from 5.6.1 to 5.7.0 (#2119) Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.6.1 to 5.7.0. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.6.1...v5.7.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix/delegate call trace (#2115) * WIP: fix delegatecall when trace is requested via custom tracer * changes to custom tracer for call, callcode, staticcall, delegatecall opcodes * fix custom tracer staticcall opcode * fix custom tracer subcalls with multi levels * comment test debug code * review error handling * fix custom call tracer for SC calls with precompiled code * fix get precompiled address and input for opcodes that have tx value * increase debug tracer e2e tests timeout * update prover image * change log to info (#2121) --------- Signed-off-by: dependabot[bot] Signed-off-by: Nikolay Nedkov Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Toni Ramírez <58293609+ToniRamirezM@users.noreply.github.com> Co-authored-by: Nikolay Nedkov Co-authored-by: Thiago Coimbra Lemos Co-authored-by: ToniRamirezM Co-authored-by: Arnau Bennassar Co-authored-by: tclemos Co-authored-by: Paolo Grisoli Co-authored-by: Cool Developer Co-authored-by: Cool Developer <125276287+C001-developer@users.noreply.github.com> Co-authored-by: CvH <109217179+cvhpoly@users.noreply.github.com> Co-authored-by: Jordi Baylina Co-authored-by: CG <118215885+cg-polygon@users.noreply.github.com> Co-authored-by: Ubuntu Co-authored-by: agnusmor <100322135+agnusmor@users.noreply.github.com> Co-authored-by: zkronos73 <94566827+zkronos73@users.noreply.github.com> Co-authored-by: zkronos73 Co-authored-by: pierce403 Co-authored-by: agnusmor Co-authored-by: Thiago Lemos Co-authored-by: nathan haim Co-authored-by: Toni Ramírez --- .github/ISSUE_TEMPLATE/bug.md | 31 + .github/ISSUE_TEMPLATE/feature.md | 17 + .github/ISSUE_TEMPLATE/question.md | 9 + .github/workflows/codeql.yml | 76 + .github/workflows/lint.yml | 7 +- .github/workflows/ok-to-test.yml | 23 - .github/workflows/push-docker-develop.yml | 24 +- .github/workflows/push-docker-tagged.yml | 33 + .github/workflows/push-docker.yml | 52 - .github/workflows/release.yml | 58 +- .github/workflows/sonarqube.yml | 22 + .github/workflows/test-e2e.yml | 90 +- .github/workflows/test-from-prover.yml | 14 +- .github/workflows/test-full-non-e2e.yml | 82 +- .github/workflows/updatedeps.yml | 11 +- .gitignore | 9 +- .golangci.yml | 5 + .goreleaser.yaml | 17 + Dockerfile | 8 +- LICENSE | 186 +- Makefile | 379 +- README.md | 17 +- aggregator/aggregator.go | 1218 +++- aggregator/aggregator_internal_test.go | 292 - aggregator/aggregator_test.go | 1387 +++++ aggregator/config.go | 35 +- aggregator/interfaces.go | 46 +- aggregator/metrics/metrics.go | 51 + .../mocks/mock_dbtx.go | 72 +- aggregator/mocks/mock_etherman.go | 60 +- aggregator/mocks/mock_ethtxmanager.go | 82 +- aggregator/mocks/mock_profitabilitychecker.go | 54 + aggregator/mocks/mock_prover.go | 224 + aggregator/mocks/mock_proverclient.go | 102 - aggregator/mocks/mock_state.go | 213 +- aggregator/pb/aggregator.pb.go | 2341 ++++++++ aggregator/pb/aggregator_grpc.pb.go | 137 + aggregator/prover/client.go | 109 - aggregator/prover/prover.go | 353 +- ci/e2e-group1/constants.go | 13 + .../ethtransfer_test.go | 0 ci/e2e-group1/preEIP155_test.go | 1 + ci/e2e-group1/shared.go | 1 + ci/e2e-group1/state_test.go | 1 - ci/e2e-group2/broadcast_test.go | 1 - ci/{e2e-group2 => e2e-group3}/sc_test.go | 0 ci/e2e-group3/shared.go | 1 + ci/e2e-group3/uniswap_test.go | 1 - ci/e2e-group4/jsonrpc1_test.go | 1 + ci/e2e-group4/shared.go | 1 + ci/e2e-group5/debug_shared.go | 1 + ci/e2e-group5/debug_test.go | 1 + ci/e2e-group5/shared.go | 1 + ci/e2e-group6/permissionlessrpc_test.go | 1 + ci/e2e-group7/jsonrpc2_test.go | 1 + ci/e2e-group7/shared.go | 1 + ci/e2e-group8/debug_calltracer_test.go | 1 + ci/e2e-group8/debug_shared.go | 1 + ci/e2e-group8/shared.go | 1 + ci/e2e-group9/forced_batches_test.go | 225 + ci/e2e-group9/forced_batches_vector_test.go | 228 + ci/e2e-group9/shared.go | 12 + cmd/approve.go | 51 +- cmd/dumpstate.go | 13 +- cmd/main.go | 94 +- cmd/run.go | 496 +- cmd/version.go | 7 +- config/config.debug.toml | 106 - config/config.go | 86 +- config/config.local.toml | 106 - config/config_test.go | 346 +- config/default.go | 146 +- .../local/local.genesis.config.json | 102 + .../environments/local/local.node.config.toml | 141 + config/environments/mainnet/example.env | 9 + config/environments/mainnet/postgresql.conf | 815 +++ .../mainnet/public.node.config.toml | 65 + .../mainnet/public.prover.config.json | 113 + config/environments/public/example.env | 9 + config/environments/public/postgresql.conf | 815 +++ .../public/public.node.config.toml | 65 + .../public/public.prover.config.json | 113 + test/test.keystore => config/example.keystore | 0 config/genesis.go | 423 -- config/initproverdb.sql | 14 - config/mainnetgenesis.go | 107 + config/metrics/prometheus/prometheus.yml | 14 + config/network.go | 328 +- config/network_test.go | 293 +- config/prover.config.local.json | 69 - config/readme.md | 2 - config/testnetgenesis.go | 108 + config/types/duration_test.go | 54 + config/types/keystore.go | 10 + db/db.go | 51 +- db/migrations/pool/0001.sql | 6 +- db/migrations/pool/0002.sql | 8 +- db/migrations/pool/0003.sql | 13 + db/migrations/pool/0004.sql | 5 + db/migrations/pool/0005.sql | 13 + db/migrations/pool/0006.sql | 7 + db/migrations/pool/0007.sql | 8 + db/migrations/pool/0008.sql | 5 + db/migrations/rpc/0001.sql | 13 - db/migrations/state/0001.sql | 77 +- db/migrations/state/0002.sql | 62 + db/migrations/state/0002_test.go | 139 + db/migrations/state/0003.sql | 8 + db/migrations/state/0004.sql | 12 + db/migrations/state/0005.sql | 20 + db/migrations/state/0006.sql | 9 + db/migrations/state/utils_test.go | 118 + db/scripts/init_event_db.sql | 14 + db/scripts/init_prover_db.sql | 14 + db/scripts/single_db_server.sql | 17 + db/single_db_server.sql | 3 - docker-compose.yml | 337 +- docs/architecture.drawio.png | Bin 165400 -> 154305 bytes docs/ci/actions.md | 2 - docs/ci/groups.md | 9 +- docs/ci/ok-to-test.md | 2 +- docs/components/account_keystore.md | 12 + docs/components/aggregator.md | 47 + docs/components/databases.md | 57 + docs/components/prover.md | 39 + docs/components/rpc.md | 45 + docs/components/sequencer.md | 37 + docs/components/synchronizer.md | 37 + docs/json-rpc-endpoints.md | 68 + docs/modes.md | 102 + docs/networks.md | 5 + docs/production-setup.md | 367 +- docs/running_local.md | 151 +- docs/zkEVM-custom-endpoints.md | 9 + encoding/encoding.go | 8 +- etherman/config.go | 7 + etherman/converters.go | 65 - etherman/errors.go | 48 + etherman/errors_test.go | 37 + etherman/etherman.go | 821 ++- etherman/etherman_test.go | 330 +- etherman/etherscan/etherscan.go | 75 + etherman/etherscan/etherscan_test.go | 39 + etherman/ethgasstation/ethgasstation.go | 64 + etherman/ethgasstation/ethgasstation_test.go | 37 + etherman/mock_etherscan.go | 56 + etherman/mock_ethgasstation.go | 56 + etherman/simulated.go | 56 +- etherman/smartcontracts/abi/mockverifier.abi | 18 +- etherman/smartcontracts/abi/polygonzkevm.abi | 1709 ++++++ .../{bridge.abi => polygonzkevmbridge.abi} | 343 +- ...ger.abi => polygonzkevmglobalexitroot.abi} | 59 +- .../smartcontracts/abi/proofofefficiency.abi | 631 -- etherman/smartcontracts/bin/bridge.bin | 1 - .../bin/globalexitrootmanager.bin | 1 - etherman/smartcontracts/bin/mockverifier.bin | 2 +- etherman/smartcontracts/bin/polygonzkevm.bin | 1 + .../smartcontracts/bin/polygonzkevmbridge.bin | 1 + .../bin/polygonzkevmglobalexitroot.bin | 1 + .../smartcontracts/bin/proofofefficiency.bin | 1 - etherman/smartcontracts/bridge/bridge.go | 1230 ---- .../globalexitrootmanager.go | 757 --- etherman/smartcontracts/matic/matic.go | 5 +- .../mockverifier/mockverifier.go | 33 +- .../polygonzkevm/polygonzkevm.go | 5308 +++++++++++++++++ .../polygonzkevmbridge/polygonzkevmbridge.go | 1666 ++++++ .../polygonzkevmglobalexitroot.go | 563 ++ .../proofofefficiency/proofofefficiency.go | 2191 ------- etherman/smartcontracts/script.sh | 6 +- etherman/types.go | 43 +- etherman/types/finalproofinputs.go | 10 + etherman/types/sequence.go | 11 +- ethtxmanager/config.go | 22 +- ethtxmanager/ethtxmanager.go | 705 ++- ethtxmanager/ethtxmanager_test.go | 674 ++- ethtxmanager/interfaces.go | 31 +- ethtxmanager/mock_etherman_test.go | 290 + ethtxmanager/mock_state_test.go | 59 + ethtxmanager/monitoredtx.go | 192 + ethtxmanager/monitoredtx_test.go | 36 + ethtxmanager/pgstorage.go | 277 + ethtxmanager/pgstorage_test.go | 300 + event/config.go | 9 + event/event.go | 90 + event/eventlog.go | 53 + event/eventlog_test.go | 38 + event/interfaces.go | 11 + event/nileventstorage/nileventstorage.go | 38 + event/pgeventstorage/pgeventstorage.go | 48 + gasprice/allbatches.go | 43 - gasprice/config.go | 18 +- gasprice/default.go | 37 +- gasprice/default_test.go | 27 + gasprice/follower.go | 77 + gasprice/follower_test.go | 39 + gasprice/gaspricesuggester.go | 43 + gasprice/interfaces.go | 6 + gasprice/lastnbatches.go | 43 +- gasprice/mock_etherman.go | 46 + gasprice/mock_pool.go | 67 + go.mod | 176 +- go.sum | 937 ++- hex/hex.go | 35 +- hex/hex_test.go | 16 + jsonrpc/{ => client}/client.go | 36 +- jsonrpc/client/zkevm.go | 55 + jsonrpc/codec.go | 165 - jsonrpc/config.go | 45 +- jsonrpc/dbtxmanager.go | 11 +- jsonrpc/dbtxmanager_test.go | 42 +- jsonrpc/debug.go | 122 - jsonrpc/endpoints_debug.go | 273 + jsonrpc/endpoints_eth.go | 1024 ++++ .../{eth_test.go => endpoints_eth_test.go} | 2256 ++++--- jsonrpc/endpoints_net.go | 19 + jsonrpc/{txpool.go => endpoints_txpool.go} | 17 +- jsonrpc/endpoints_web3.go | 27 + .../{web3_test.go => endpoints_web3_test.go} | 3 +- jsonrpc/endpoints_zkevm.go | 169 + jsonrpc/endpoints_zkevm.openrpc.json | 566 ++ jsonrpc/endpoints_zkevm_test.go | 1136 ++++ jsonrpc/errors.go | 42 - jsonrpc/errors_test.go | 24 - jsonrpc/eth.go | 765 --- jsonrpc/handler.go | 149 +- jsonrpc/interfaces.go | 73 +- jsonrpc/metrics/metrics.go | 74 + jsonrpc/mock_gasPriceEstimator_test.go | 53 - jsonrpc/mock_state_test.go | 615 -- jsonrpc/mock_storage.go | 220 + jsonrpc/mock_storage_test.go | 146 - jsonrpc/mocks/mock_dbtx.go | 299 + .../{mock_pool_test.go => mocks/mock_pool.go} | 80 +- jsonrpc/mocks/mock_state.go | 945 +++ jsonrpc/net.go | 17 - jsonrpc/pgstorage.go | 121 - jsonrpc/query.go | 78 +- jsonrpc/server.go | 269 +- jsonrpc/server_test.go | 66 +- jsonrpc/storage.go | 170 + jsonrpc/types.go | 398 -- jsonrpc/types/codec.go | 416 ++ jsonrpc/{ => types}/codec_test.go | 85 +- jsonrpc/types/errors.go | 63 + jsonrpc/types/errors_test.go | 24 + jsonrpc/types/interfaces.go | 66 + jsonrpc/types/query.go | 14 + jsonrpc/types/types.go | 595 ++ jsonrpc/types/types_test.go | 239 + jsonrpc/web3.go | 22 - jsonrpc/zkevm.go | 64 - jsonrpc/zkevm_test.go | 249 - log/config.go | 2 + log/log.go | 220 +- log/log_test.go | 5 +- merkletree/pb/statedb.pb.go | 868 ++- merkletree/pb/statedb_grpc.pb.go | 82 +- merkletree/tree.go | 7 + metrics/api.go | 16 + metrics/config.go | 11 + metrics/prometheus.go | 677 +++ metrics/prometheus_test.go | 371 ++ pool/config.go | 31 + pool/errors.go | 13 + pool/interfaces.go | 26 +- pool/pgpoolstorage/pgpoolstorage.go | 306 +- pool/pool.go | 381 +- pool/pool_test.go | 1141 ++-- pool/transaction.go | 77 +- pool/transaction_test.go | 67 - .../src/proto/aggregator/v1/aggregator.proto | 296 + proto/src/proto/broadcast/v1/broadcast.proto | 40 - proto/src/proto/executor/v1/executor.proto | 191 +- proto/src/proto/statedb/v1/statedb.proto | 75 +- proto/src/proto/zkprover/v1/zk_prover.proto | 233 - proverclient/config.go | 7 - proverclient/pb/zk_prover.pb.go | 1669 ------ proverclient/pb/zk_prover_grpc.pb.go | 246 - scripts/uniswap/main.go | 312 - sequencer/addrqueue.go | 196 + sequencer/addrqueue_test.go | 153 + sequencer/batchbuilder.go | 520 -- sequencer/broadcast/client.go | 30 - sequencer/broadcast/config.go | 7 - sequencer/broadcast/interfaces.go | 19 - sequencer/broadcast/mocks/mock_state.go | 150 - sequencer/broadcast/pb/broadcast.pb.go | 393 -- sequencer/broadcast/pb/broadcast_grpc.pb.go | 142 - sequencer/broadcast/server.go | 153 - sequencer/broadcast/server_test.go | 244 - sequencer/closingchecker.go | 94 - sequencer/closingsignalsmanager.go | 106 + sequencer/closingsignalsmanager_test.go | 161 + sequencer/config.go | 133 +- sequencer/dbmanager.go | 576 ++ sequencer/dbmanager_test.go | 176 + sequencer/efficiencylist.go | 126 + sequencer/efficiencylist_test.go | 94 + sequencer/errors.go | 8 + sequencer/finalizer.go | 951 +++ sequencer/finalizer_test.go | 1135 ++++ sequencer/interfaces.go | 119 +- sequencer/metrics/metrics.go | 153 + sequencer/mock_db_manager.go | 603 ++ sequencer/mock_dbtx.go | 299 + sequencer/{mocks => }/mock_etherman.go | 102 +- sequencer/mock_pool.go | 157 + sequencer/mock_state.go | 838 +++ sequencer/mock_worker.go | 149 + sequencer/mocks/mock_txmanager.go | 34 - sequencer/pendingtxsqueue.go | 208 - sequencer/pendingtxsqueue_test.go | 227 - sequencer/profitabilitychecker/config.go | 7 - sequencer/profitabilitychecker/interfaces.go | 19 - .../mocks/mock_etherman.go | 52 - .../profitabilitychecker.go | 87 - .../profitabilitychecker_test.go | 115 - sequencer/sequencer.go | 385 +- sequencer/sequencer_internal_test.go | 302 - sequencer/sequencer_test.go | 265 - sequencer/sequencesender.go | 218 - sequencer/txtracker.go | 157 + sequencer/txtracker_test.go | 100 + sequencer/worker.go | 328 + sequencer/worker_test.go | 312 + sequencesender/config.go | 25 + sequencesender/interfaces.go | 40 + sequencesender/sequencesender.go | 328 + sonar-project.properties | 1 + state/batch.go | 442 +- state/config.go | 3 + state/converters.go | 176 +- state/crypto.go | 7 +- state/errors.go | 47 + state/fakedb.go | 160 +- state/forcedbatch.go | 1 - state/forkid.go | 34 + state/genesis.go | 162 +- state/genesis_test.go | 2 +- state/globalexitroot.go | 12 +- state/helper.go | 153 +- state/helper_test.go | 99 + state/l2block.go | 111 + state/metrics/metrics.go | 49 + state/pgstatestorage.go | 1067 +++- state/pgstatestorage_test.go | 439 ++ state/proof.go | 22 + state/runtime/executor/client.go | 30 +- state/runtime/executor/errors.go | 361 +- state/runtime/executor/pb/executor.pb.go | 1410 +++-- state/runtime/executor/pb/executor_grpc.pb.go | 16 +- state/runtime/fakevm/analysis.go | 118 + state/runtime/fakevm/common.go | 82 + state/runtime/fakevm/contract.go | 194 + state/runtime/fakevm/contracts.go | 1050 ++++ state/runtime/fakevm/eips.go | 243 + state/runtime/fakevm/errors.go | 73 + state/runtime/fakevm/fakedb.go | 71 +- state/runtime/fakevm/fakevm.go | 498 +- state/runtime/fakevm/gas.go | 53 + state/runtime/fakevm/gas_table.go | 477 ++ state/runtime/fakevm/instructions.go | 919 +++ state/runtime/fakevm/interpreter.go | 231 +- state/runtime/fakevm/jump_table.go | 1064 ++++ state/runtime/fakevm/logger.go | 12 +- state/runtime/fakevm/memory.go | 25 +- state/runtime/fakevm/memory_table.go | 113 + state/runtime/fakevm/opcodes.go | 1061 ++-- state/runtime/fakevm/operations_acl.go | 244 + state/runtime/fakevm/stack.go | 46 +- state/runtime/fakevm/stack_table.go | 42 + .../runtime/instrumentation/executortrace.go | 4 +- .../instrumentation/intrumentation_test.go | 6 +- state/runtime/instrumentation/js/goja.go | 394 +- .../instrumentation/tracers/native/4byte.go | 132 + .../instrumentation/tracers/native/call.go | 270 + .../tracers/native/call_flat.go | 379 ++ .../tracers/native/gen_account_json.go | 56 + .../tracers/native/gen_callframe_json.go | 107 + .../tracers/native/gen_flatcallaction_json.go | 110 + .../tracers/native/gen_flatcallresult_json.go | 55 + .../instrumentation/tracers/native/mux.go | 138 + .../instrumentation/tracers/native/noop.go | 77 + .../tracers/native/prestate.go | 285 + .../instrumentation/tracers/tracers.go | 75 +- state/runtime/runtime.go | 62 +- state/state.go | 1278 +--- state/state_test.go | 1311 ++-- state/transaction.go | 1075 ++++ state/types.go | 222 +- synchronizer/config.go | 3 +- synchronizer/interfaces.go | 45 +- synchronizer/mock_dbtx.go | 32 +- synchronizer/mock_etherman.go | 103 +- synchronizer/mock_ethtxmanager.go | 44 + synchronizer/mock_pool.go | 59 + synchronizer/mock_state.go | 302 +- synchronizer/mock_zkevmclient.go | 82 + synchronizer/synchronizer.go | 1038 +++- synchronizer/synchronizer_test.go | 965 ++- test/Makefile | 530 ++ test/aggregator.keystore | 1 + test/benchmarks/interfaces.go | 14 - .../sequencer/common/metrics/metrics.go | 108 + .../sequencer/common/params/constants.go | 16 + .../sequencer/common/params/variables.go | 30 + .../sequencer/common/setup/setup.go | 130 + .../common/transactions/transactions.go | 105 + .../pool_processing_erc20_test.go | 97 + .../sequencer/erc20-transfers/tx_sender.go | 40 + .../eth-transfers/pool_processing_eth_test.go | 54 + .../sequencer/eth-transfers/tx_sender.go | 47 + .../scripts/common/environment/constants.go | 35 + .../scripts/common/environment/init.go | 97 + .../sequencer/scripts/common/results/print.go | 19 + .../sequencer/scripts/erc20-transfers/main.go | 57 + .../sequencer/scripts/eth-transfers/main.go | 51 + test/benchmarks/sequencer_test.go | 148 - test/config/config.test.toml | 106 - test/config/debug.node.config.toml | 152 + test/config/grafana/dashboard-dockers.json | 629 ++ test/config/grafana/dashboard-node.json | 389 ++ test/config/grafana/dashboards.yml | 13 + test/config/grafana/datasources.yml | 18 + test/config/prover.config.test.json | 69 - test/config/telegraf.conf | 15 + test/config/test.genesis.config.json | 102 + test/config/test.node.config.toml | 155 + .../test.permissionless.prover.config.json | 85 + test/config/test.prover.config.json | 86 + test/constants/environment_variables.go | 8 + test/constants/smart_contracts.go | 7 + test/contracts/auto/Called.sol | 30 + test/contracts/auto/Caller.sol | 74 + test/contracts/auto/ChainCallLevel1.sol | 26 + test/contracts/auto/ChainCallLevel2.sol | 27 + test/contracts/auto/ChainCallLevel3.sol | 23 + test/contracts/auto/ChainCallLevel4.sol | 16 + test/contracts/auto/Creates.sol | 67 + test/contracts/auto/DelegatecallReceiver.sol | 26 - test/contracts/auto/DelegatecallSender.sol | 23 - test/contracts/auto/EmitLog2.sol | 3 + test/contracts/auto/Storage.sol | 4 + test/contracts/bin/Called/Called.go | 312 + test/contracts/bin/Caller/Caller.go | 371 ++ .../bin/ChainCallLevel1/ChainCallLevel1.go | 224 + .../bin/ChainCallLevel2/ChainCallLevel2.go | 255 + .../bin/ChainCallLevel3/ChainCallLevel3.go | 255 + .../bin/ChainCallLevel4/ChainCallLevel4.go | 255 + test/contracts/bin/Counter/Counter.go | 5 +- test/contracts/bin/Creates/Creates.go | 360 ++ .../DelegatecallReceiver.go | 262 - .../DelegatecallSender/DelegatecallSender.go | 254 - test/contracts/bin/Destruct/Destruct.go | 5 +- test/contracts/bin/Double/Double.go | 5 +- test/contracts/bin/ERC20/ERC20.go | 5 +- test/contracts/bin/EmitLog/EmitLog.go | 5 +- test/contracts/bin/EmitLog2/EmitLog2.go | 7 +- test/contracts/bin/FailureTest/FailureTest.go | 5 +- test/contracts/bin/Interaction/Interaction.go | 5 +- test/contracts/bin/Read/Read.go | 5 +- test/contracts/bin/Revert/Revert.go | 5 +- test/contracts/bin/Revert2/Revert2.go | 5 +- test/contracts/bin/Storage/Storage.go | 30 +- .../bin/StorageOnDeploy/StorageOnDeploy.go | 5 +- test/contracts/bin/WETH/WETH.go | 5 +- .../v2/core/UniswapV2ERC20/UniswapV2ERC20.go | 5 +- .../core/UniswapV2Factory/UniswapV2Factory.go | 5 +- .../v2/core/UniswapV2Pair/UniswapV2Pair.go | 5 +- .../UniswapInterfaceMulticall.go | 5 +- .../UniswapV2Migrator/UniswapV2Migrator.go | 5 +- .../UniswapV2Router02/UniswapV2Router02.go | 5 +- .../compiled/ERC20Token/ERC20Token.abi | 1 + .../compiled/ERC20Token/ERC20Token.bin | 1 + .../MultiSigWallet/MultiSigWallet.abi | 1 + .../MultiSigWallet/MultiSigWallet.bin | 1 + test/dbutils/dbutils.go | 18 +- test/docker-compose.yml | 447 ++ test/e2e/broadcast_test.go | 152 - test/e2e/debug_calltracer_test.go | 414 ++ test/e2e/debug_shared.go | 525 ++ test/e2e/debug_test.go | 666 +++ test/e2e/ethtransfer_test.go | 54 +- test/e2e/forced_batches_test.go | 231 + test/e2e/forced_batches_vector_test.go | 228 + test/e2e/jsonrpc1_test.go | 536 ++ test/e2e/jsonrpc2_test.go | 472 ++ test/e2e/jsonrpc_test.go | 186 - test/e2e/permissionlessrpc_test.go | 130 + test/e2e/pool_test.go | 4 +- test/e2e/preEIP155_test.go | 90 + test/e2e/sc_test.go | 76 +- test/e2e/shared.go | 106 +- test/e2e/state_test.go | 33 +- test/e2e/uniswap_test.go | 10 +- test/operations/manager.go | 504 +- test/operations/wait.go | 166 +- test/scripts/batchsender/README.md | 71 + test/scripts/batchsender/main.go | 338 ++ {scripts => test/scripts}/cmd/compilesc.go | 2 +- .../scripts}/cmd/compilesc/manager.go | 3 +- {scripts => test/scripts}/cmd/dependencies.go | 2 +- .../scripts}/cmd/dependencies/files.go | 0 .../scripts}/cmd/dependencies/files_test.go | 0 .../scripts}/cmd/dependencies/github.go | 8 +- .../scripts}/cmd/dependencies/github_test.go | 0 .../scripts}/cmd/dependencies/images.go | 0 .../scripts}/cmd/dependencies/images_test.go | 0 .../scripts}/cmd/dependencies/manager.go | 0 .../scripts}/cmd/dependencies/protobuffers.go | 0 .../scripts}/cmd/dependencies/testvectors.go | 0 {scripts => test/scripts}/cmd/main.go | 0 {scripts => test/scripts}/deploy_sc/main.go | 22 +- .../scripts}/init_network/main.go | 2 +- .../scripts}/postgres/prover-user.sql | 0 {scripts => test/scripts}/postgres/run.sh | 0 test/scripts/sendForcedBatch/README.md | 5 + test/scripts/sendForcedBatch/main.go | 175 + test/scripts/send_transfers/main.go | 108 + test/scripts/sequenceForcedBatch/README.md | 5 + test/scripts/sequenceForcedBatch/main.go | 151 + test/scripts/txsender/README.md | 36 + test/scripts/txsender/main.go | 217 + test/scripts/uniswap/main.go | 277 + test/sequencer.keystore | 1 + test/testutils/utils.go | 33 + test/tracers/tracer.json | 2 +- test/vectors/smartcontract.go | 4 +- .../state-transition/forced-tx/erc20_0.json | 484 ++ .../eth-CallEcrecoverInvalidSignature.json | 53 + .../state-transition/forced-tx/general_0.json | 41 + .../state-transition/forced-tx/general_1.json | 80 + .../state-transition/forced-tx/general_2.json | 41 + .../state-transition/forced-tx/general_3.json | 41 + .../state-transition/forced-tx/general_4.json | 41 + .../state-transition/forced-tx/general_5.json | 41 + .../state-transition/forced-tx/general_6.json | 41 + .../state-transition/forced-tx/general_7.json | 41 + .../state-transition/forced-tx/mynft_0.json | 483 ++ .../forced-tx/test-deploy_0.json | 53 + .../forced-tx/test-deploy_1.json | 50 + .../forced-tx/test-deploy_2.json | 50 + .../forced-tx/test-deploy_3.json | 167 + .../forced-tx/test-deploy_4.json | 62 + .../forced-tx/test-deploy_5.json | 50 + .../forced-tx/test-deploy_6.json | 50 + .../forced-tx/test-deploy_7.json | 50 + .../forced-tx/test-deploy_8.json | 50 + .../forced-tx/test-deploy_9.json | 50 + .../forced-tx/uniswapv2_1.json | 1151 ++++ test/vectors/src/tx-hash-ethereum/rlp.json | 16 + test/vectors/statetransition.go | 4 +- test/vectors/statetransition_v2.go | 36 + test/vectors/vectors_v2.go | 89 + tools/executor/docker-compose.yml | 2 +- tools/executor/main.go | 44 +- .../fail-deploy-uniswap-repeated-nonce.json | 12 +- tools/genesis/generator.go | 199 - tools/network/network.go | 10 +- tools/rlp/main.go | 119 +- tools/zkevmprovermock/Dockerfile | 2 +- tools/zkevmprovermock/cmd/client.go | 12 - tools/zkevmprovermock/cmd/main.go | 77 - tools/zkevmprovermock/cmd/server.go | 46 - tools/zkevmprovermock/server/executor.go | 411 -- tools/zkevmprovermock/server/statedb.go | 158 - tools/zkevmprovermock/testvector/main.go | 229 - .../testvector/testvector_test.go | 859 --- version.go | 25 + version.mk | 4 + 570 files changed, 76747 insertions(+), 29082 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/workflows/codeql.yml delete mode 100644 .github/workflows/ok-to-test.yml create mode 100644 .github/workflows/push-docker-tagged.yml delete mode 100644 .github/workflows/push-docker.yml create mode 100644 .github/workflows/sonarqube.yml create mode 100644 .goreleaser.yaml delete mode 100644 aggregator/aggregator_internal_test.go create mode 100644 aggregator/aggregator_test.go create mode 100644 aggregator/metrics/metrics.go rename jsonrpc/mock_dbtx_test.go => aggregator/mocks/mock_dbtx.go (74%) create mode 100644 aggregator/mocks/mock_profitabilitychecker.go create mode 100644 aggregator/mocks/mock_prover.go delete mode 100644 aggregator/mocks/mock_proverclient.go create mode 100644 aggregator/pb/aggregator.pb.go create mode 100644 aggregator/pb/aggregator_grpc.pb.go delete mode 100644 aggregator/prover/client.go create mode 100644 ci/e2e-group1/constants.go rename ci/{e2e-group2 => e2e-group1}/ethtransfer_test.go (100%) create mode 120000 ci/e2e-group1/preEIP155_test.go create mode 120000 ci/e2e-group1/shared.go delete mode 120000 ci/e2e-group1/state_test.go delete mode 120000 ci/e2e-group2/broadcast_test.go rename ci/{e2e-group2 => e2e-group3}/sc_test.go (100%) create mode 120000 ci/e2e-group3/shared.go delete mode 120000 ci/e2e-group3/uniswap_test.go create mode 120000 ci/e2e-group4/jsonrpc1_test.go create mode 120000 ci/e2e-group4/shared.go create mode 120000 ci/e2e-group5/debug_shared.go create mode 120000 ci/e2e-group5/debug_test.go create mode 120000 ci/e2e-group5/shared.go create mode 120000 ci/e2e-group6/permissionlessrpc_test.go create mode 120000 ci/e2e-group7/jsonrpc2_test.go create mode 120000 ci/e2e-group7/shared.go create mode 120000 ci/e2e-group8/debug_calltracer_test.go create mode 120000 ci/e2e-group8/debug_shared.go create mode 120000 ci/e2e-group8/shared.go create mode 100644 ci/e2e-group9/forced_batches_test.go create mode 100644 ci/e2e-group9/forced_batches_vector_test.go create mode 100644 ci/e2e-group9/shared.go delete mode 100644 config/config.debug.toml delete mode 100644 config/config.local.toml create mode 100644 config/environments/local/local.genesis.config.json create mode 100644 config/environments/local/local.node.config.toml create mode 100644 config/environments/mainnet/example.env create mode 100644 config/environments/mainnet/postgresql.conf create mode 100644 config/environments/mainnet/public.node.config.toml create mode 100644 config/environments/mainnet/public.prover.config.json create mode 100644 config/environments/public/example.env create mode 100644 config/environments/public/postgresql.conf create mode 100644 config/environments/public/public.node.config.toml create mode 100644 config/environments/public/public.prover.config.json rename test/test.keystore => config/example.keystore (100%) delete mode 100644 config/genesis.go delete mode 100644 config/initproverdb.sql create mode 100644 config/mainnetgenesis.go create mode 100644 config/metrics/prometheus/prometheus.yml delete mode 100644 config/prover.config.local.json create mode 100644 config/testnetgenesis.go create mode 100644 config/types/duration_test.go create mode 100644 config/types/keystore.go create mode 100644 db/migrations/pool/0003.sql create mode 100644 db/migrations/pool/0004.sql create mode 100644 db/migrations/pool/0005.sql create mode 100644 db/migrations/pool/0006.sql create mode 100644 db/migrations/pool/0007.sql create mode 100644 db/migrations/pool/0008.sql delete mode 100644 db/migrations/rpc/0001.sql create mode 100644 db/migrations/state/0002.sql create mode 100644 db/migrations/state/0002_test.go create mode 100644 db/migrations/state/0003.sql create mode 100644 db/migrations/state/0004.sql create mode 100644 db/migrations/state/0005.sql create mode 100644 db/migrations/state/0006.sql create mode 100644 db/migrations/state/utils_test.go create mode 100644 db/scripts/init_event_db.sql create mode 100644 db/scripts/init_prover_db.sql create mode 100644 db/scripts/single_db_server.sql delete mode 100644 db/single_db_server.sql create mode 100644 docs/components/account_keystore.md create mode 100644 docs/components/aggregator.md create mode 100644 docs/components/databases.md create mode 100644 docs/components/prover.md create mode 100644 docs/components/rpc.md create mode 100644 docs/components/sequencer.md create mode 100644 docs/components/synchronizer.md create mode 100644 docs/json-rpc-endpoints.md create mode 100644 docs/modes.md create mode 100644 docs/networks.md create mode 100644 docs/zkEVM-custom-endpoints.md delete mode 100644 etherman/converters.go create mode 100644 etherman/errors.go create mode 100644 etherman/errors_test.go create mode 100644 etherman/etherscan/etherscan.go create mode 100644 etherman/etherscan/etherscan_test.go create mode 100644 etherman/ethgasstation/ethgasstation.go create mode 100644 etherman/ethgasstation/ethgasstation_test.go create mode 100644 etherman/mock_etherscan.go create mode 100644 etherman/mock_ethgasstation.go create mode 100644 etherman/smartcontracts/abi/polygonzkevm.abi rename etherman/smartcontracts/abi/{bridge.abi => polygonzkevmbridge.abi} (61%) rename etherman/smartcontracts/abi/{globalexitrootmanager.abi => polygonzkevmglobalexitroot.abi} (79%) delete mode 100644 etherman/smartcontracts/abi/proofofefficiency.abi delete mode 100644 etherman/smartcontracts/bin/bridge.bin delete mode 100644 etherman/smartcontracts/bin/globalexitrootmanager.bin create mode 100644 etherman/smartcontracts/bin/polygonzkevm.bin create mode 100644 etherman/smartcontracts/bin/polygonzkevmbridge.bin create mode 100644 etherman/smartcontracts/bin/polygonzkevmglobalexitroot.bin delete mode 100644 etherman/smartcontracts/bin/proofofefficiency.bin delete mode 100644 etherman/smartcontracts/bridge/bridge.go delete mode 100644 etherman/smartcontracts/globalexitrootmanager/globalexitrootmanager.go create mode 100644 etherman/smartcontracts/polygonzkevm/polygonzkevm.go create mode 100644 etherman/smartcontracts/polygonzkevmbridge/polygonzkevmbridge.go create mode 100644 etherman/smartcontracts/polygonzkevmglobalexitroot/polygonzkevmglobalexitroot.go delete mode 100644 etherman/smartcontracts/proofofefficiency/proofofefficiency.go create mode 100644 etherman/types/finalproofinputs.go create mode 100644 ethtxmanager/mock_etherman_test.go create mode 100644 ethtxmanager/mock_state_test.go create mode 100644 ethtxmanager/monitoredtx.go create mode 100644 ethtxmanager/monitoredtx_test.go create mode 100644 ethtxmanager/pgstorage.go create mode 100644 ethtxmanager/pgstorage_test.go create mode 100644 event/config.go create mode 100644 event/event.go create mode 100644 event/eventlog.go create mode 100644 event/eventlog_test.go create mode 100644 event/interfaces.go create mode 100644 event/nileventstorage/nileventstorage.go create mode 100644 event/pgeventstorage/pgeventstorage.go delete mode 100644 gasprice/allbatches.go create mode 100644 gasprice/default_test.go create mode 100644 gasprice/follower.go create mode 100644 gasprice/follower_test.go create mode 100644 gasprice/gaspricesuggester.go create mode 100644 gasprice/mock_etherman.go create mode 100644 gasprice/mock_pool.go create mode 100644 hex/hex_test.go rename jsonrpc/{ => client}/client.go (60%) create mode 100644 jsonrpc/client/zkevm.go delete mode 100644 jsonrpc/codec.go delete mode 100644 jsonrpc/debug.go create mode 100644 jsonrpc/endpoints_debug.go create mode 100644 jsonrpc/endpoints_eth.go rename jsonrpc/{eth_test.go => endpoints_eth_test.go} (58%) create mode 100644 jsonrpc/endpoints_net.go rename jsonrpc/{txpool.go => endpoints_txpool.go} (67%) create mode 100644 jsonrpc/endpoints_web3.go rename jsonrpc/{web3_test.go => endpoints_web3_test.go} (92%) create mode 100644 jsonrpc/endpoints_zkevm.go create mode 100644 jsonrpc/endpoints_zkevm.openrpc.json create mode 100644 jsonrpc/endpoints_zkevm_test.go delete mode 100644 jsonrpc/errors.go delete mode 100644 jsonrpc/errors_test.go delete mode 100644 jsonrpc/eth.go create mode 100644 jsonrpc/metrics/metrics.go delete mode 100644 jsonrpc/mock_gasPriceEstimator_test.go delete mode 100644 jsonrpc/mock_state_test.go create mode 100644 jsonrpc/mock_storage.go delete mode 100644 jsonrpc/mock_storage_test.go create mode 100644 jsonrpc/mocks/mock_dbtx.go rename jsonrpc/{mock_pool_test.go => mocks/mock_pool.go} (62%) create mode 100644 jsonrpc/mocks/mock_state.go delete mode 100644 jsonrpc/net.go delete mode 100644 jsonrpc/pgstorage.go create mode 100644 jsonrpc/storage.go delete mode 100644 jsonrpc/types.go create mode 100644 jsonrpc/types/codec.go rename jsonrpc/{ => types}/codec_test.go (65%) create mode 100644 jsonrpc/types/errors.go create mode 100644 jsonrpc/types/errors_test.go create mode 100644 jsonrpc/types/interfaces.go create mode 100644 jsonrpc/types/query.go create mode 100644 jsonrpc/types/types.go create mode 100644 jsonrpc/types/types_test.go delete mode 100644 jsonrpc/web3.go delete mode 100644 jsonrpc/zkevm.go delete mode 100644 jsonrpc/zkevm_test.go create mode 100644 metrics/api.go create mode 100644 metrics/config.go create mode 100644 metrics/prometheus.go create mode 100644 metrics/prometheus_test.go create mode 100644 pool/config.go delete mode 100644 pool/transaction_test.go create mode 100644 proto/src/proto/aggregator/v1/aggregator.proto delete mode 100644 proto/src/proto/broadcast/v1/broadcast.proto delete mode 100644 proto/src/proto/zkprover/v1/zk_prover.proto delete mode 100644 proverclient/config.go delete mode 100644 proverclient/pb/zk_prover.pb.go delete mode 100644 proverclient/pb/zk_prover_grpc.pb.go delete mode 100644 scripts/uniswap/main.go create mode 100644 sequencer/addrqueue.go create mode 100644 sequencer/addrqueue_test.go delete mode 100644 sequencer/batchbuilder.go delete mode 100644 sequencer/broadcast/client.go delete mode 100644 sequencer/broadcast/config.go delete mode 100644 sequencer/broadcast/interfaces.go delete mode 100644 sequencer/broadcast/mocks/mock_state.go delete mode 100644 sequencer/broadcast/pb/broadcast.pb.go delete mode 100644 sequencer/broadcast/pb/broadcast_grpc.pb.go delete mode 100644 sequencer/broadcast/server.go delete mode 100644 sequencer/broadcast/server_test.go delete mode 100644 sequencer/closingchecker.go create mode 100644 sequencer/closingsignalsmanager.go create mode 100644 sequencer/closingsignalsmanager_test.go create mode 100644 sequencer/dbmanager.go create mode 100644 sequencer/dbmanager_test.go create mode 100644 sequencer/efficiencylist.go create mode 100644 sequencer/efficiencylist_test.go create mode 100644 sequencer/errors.go create mode 100644 sequencer/finalizer.go create mode 100644 sequencer/finalizer_test.go create mode 100644 sequencer/metrics/metrics.go create mode 100644 sequencer/mock_db_manager.go create mode 100644 sequencer/mock_dbtx.go rename sequencer/{mocks => }/mock_etherman.go (58%) create mode 100644 sequencer/mock_pool.go create mode 100644 sequencer/mock_state.go create mode 100644 sequencer/mock_worker.go delete mode 100644 sequencer/mocks/mock_txmanager.go delete mode 100644 sequencer/pendingtxsqueue.go delete mode 100644 sequencer/pendingtxsqueue_test.go delete mode 100644 sequencer/profitabilitychecker/config.go delete mode 100644 sequencer/profitabilitychecker/interfaces.go delete mode 100644 sequencer/profitabilitychecker/mocks/mock_etherman.go delete mode 100644 sequencer/profitabilitychecker/profitabilitychecker.go delete mode 100644 sequencer/profitabilitychecker/profitabilitychecker_test.go delete mode 100644 sequencer/sequencer_internal_test.go delete mode 100644 sequencer/sequencer_test.go delete mode 100644 sequencer/sequencesender.go create mode 100644 sequencer/txtracker.go create mode 100644 sequencer/txtracker_test.go create mode 100644 sequencer/worker.go create mode 100644 sequencer/worker_test.go create mode 100644 sequencesender/config.go create mode 100644 sequencesender/interfaces.go create mode 100644 sequencesender/sequencesender.go create mode 100644 sonar-project.properties create mode 100644 state/forkid.go create mode 100644 state/helper_test.go create mode 100644 state/l2block.go create mode 100644 state/metrics/metrics.go create mode 100644 state/pgstatestorage_test.go create mode 100644 state/proof.go create mode 100644 state/runtime/fakevm/analysis.go create mode 100644 state/runtime/fakevm/common.go create mode 100644 state/runtime/fakevm/contract.go create mode 100644 state/runtime/fakevm/contracts.go create mode 100644 state/runtime/fakevm/eips.go create mode 100644 state/runtime/fakevm/errors.go create mode 100644 state/runtime/fakevm/gas.go create mode 100644 state/runtime/fakevm/gas_table.go create mode 100644 state/runtime/fakevm/instructions.go create mode 100644 state/runtime/fakevm/jump_table.go create mode 100644 state/runtime/fakevm/memory_table.go create mode 100644 state/runtime/fakevm/operations_acl.go create mode 100644 state/runtime/fakevm/stack_table.go create mode 100644 state/runtime/instrumentation/tracers/native/4byte.go create mode 100644 state/runtime/instrumentation/tracers/native/call.go create mode 100644 state/runtime/instrumentation/tracers/native/call_flat.go create mode 100644 state/runtime/instrumentation/tracers/native/gen_account_json.go create mode 100644 state/runtime/instrumentation/tracers/native/gen_callframe_json.go create mode 100644 state/runtime/instrumentation/tracers/native/gen_flatcallaction_json.go create mode 100644 state/runtime/instrumentation/tracers/native/gen_flatcallresult_json.go create mode 100644 state/runtime/instrumentation/tracers/native/mux.go create mode 100644 state/runtime/instrumentation/tracers/native/noop.go create mode 100644 state/runtime/instrumentation/tracers/native/prestate.go create mode 100644 synchronizer/mock_ethtxmanager.go create mode 100644 synchronizer/mock_pool.go create mode 100644 synchronizer/mock_zkevmclient.go create mode 100644 test/Makefile create mode 100644 test/aggregator.keystore delete mode 100644 test/benchmarks/interfaces.go create mode 100644 test/benchmarks/sequencer/common/metrics/metrics.go create mode 100644 test/benchmarks/sequencer/common/params/constants.go create mode 100644 test/benchmarks/sequencer/common/params/variables.go create mode 100644 test/benchmarks/sequencer/common/setup/setup.go create mode 100644 test/benchmarks/sequencer/common/transactions/transactions.go create mode 100644 test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go create mode 100644 test/benchmarks/sequencer/erc20-transfers/tx_sender.go create mode 100644 test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go create mode 100644 test/benchmarks/sequencer/eth-transfers/tx_sender.go create mode 100644 test/benchmarks/sequencer/scripts/common/environment/constants.go create mode 100644 test/benchmarks/sequencer/scripts/common/environment/init.go create mode 100644 test/benchmarks/sequencer/scripts/common/results/print.go create mode 100644 test/benchmarks/sequencer/scripts/erc20-transfers/main.go create mode 100644 test/benchmarks/sequencer/scripts/eth-transfers/main.go delete mode 100644 test/benchmarks/sequencer_test.go delete mode 100644 test/config/config.test.toml create mode 100644 test/config/debug.node.config.toml create mode 100644 test/config/grafana/dashboard-dockers.json create mode 100644 test/config/grafana/dashboard-node.json create mode 100644 test/config/grafana/dashboards.yml create mode 100644 test/config/grafana/datasources.yml delete mode 100644 test/config/prover.config.test.json create mode 100644 test/config/telegraf.conf create mode 100644 test/config/test.genesis.config.json create mode 100644 test/config/test.node.config.toml create mode 100644 test/config/test.permissionless.prover.config.json create mode 100644 test/config/test.prover.config.json create mode 100644 test/constants/environment_variables.go create mode 100644 test/constants/smart_contracts.go create mode 100644 test/contracts/auto/Called.sol create mode 100644 test/contracts/auto/Caller.sol create mode 100644 test/contracts/auto/ChainCallLevel1.sol create mode 100644 test/contracts/auto/ChainCallLevel2.sol create mode 100644 test/contracts/auto/ChainCallLevel3.sol create mode 100644 test/contracts/auto/ChainCallLevel4.sol create mode 100644 test/contracts/auto/Creates.sol delete mode 100644 test/contracts/auto/DelegatecallReceiver.sol delete mode 100644 test/contracts/auto/DelegatecallSender.sol create mode 100644 test/contracts/bin/Called/Called.go create mode 100644 test/contracts/bin/Caller/Caller.go create mode 100644 test/contracts/bin/ChainCallLevel1/ChainCallLevel1.go create mode 100644 test/contracts/bin/ChainCallLevel2/ChainCallLevel2.go create mode 100644 test/contracts/bin/ChainCallLevel3/ChainCallLevel3.go create mode 100644 test/contracts/bin/ChainCallLevel4/ChainCallLevel4.go create mode 100644 test/contracts/bin/Creates/Creates.go delete mode 100644 test/contracts/bin/DelegatecallReceiver/DelegatecallReceiver.go delete mode 100644 test/contracts/bin/DelegatecallSender/DelegatecallSender.go create mode 100644 test/contracts/compiled/ERC20Token/ERC20Token.abi create mode 100644 test/contracts/compiled/ERC20Token/ERC20Token.bin create mode 100644 test/contracts/compiled/MultiSigWallet/MultiSigWallet.abi create mode 100644 test/contracts/compiled/MultiSigWallet/MultiSigWallet.bin create mode 100644 test/docker-compose.yml delete mode 100644 test/e2e/broadcast_test.go create mode 100644 test/e2e/debug_calltracer_test.go create mode 100644 test/e2e/debug_shared.go create mode 100644 test/e2e/debug_test.go create mode 100644 test/e2e/forced_batches_test.go create mode 100644 test/e2e/forced_batches_vector_test.go create mode 100644 test/e2e/jsonrpc1_test.go create mode 100644 test/e2e/jsonrpc2_test.go delete mode 100644 test/e2e/jsonrpc_test.go create mode 100644 test/e2e/permissionlessrpc_test.go create mode 100644 test/e2e/preEIP155_test.go create mode 100644 test/scripts/batchsender/README.md create mode 100644 test/scripts/batchsender/main.go rename {scripts => test/scripts}/cmd/compilesc.go (75%) rename {scripts => test/scripts}/cmd/compilesc/manager.go (98%) rename {scripts => test/scripts}/cmd/dependencies.go (90%) rename {scripts => test/scripts}/cmd/dependencies/files.go (100%) rename {scripts => test/scripts}/cmd/dependencies/files_test.go (100%) rename {scripts => test/scripts}/cmd/dependencies/github.go (96%) rename {scripts => test/scripts}/cmd/dependencies/github_test.go (100%) rename {scripts => test/scripts}/cmd/dependencies/images.go (100%) rename {scripts => test/scripts}/cmd/dependencies/images_test.go (100%) rename {scripts => test/scripts}/cmd/dependencies/manager.go (100%) rename {scripts => test/scripts}/cmd/dependencies/protobuffers.go (100%) rename {scripts => test/scripts}/cmd/dependencies/testvectors.go (100%) rename {scripts => test/scripts}/cmd/main.go (100%) rename {scripts => test/scripts}/deploy_sc/main.go (87%) rename {scripts => test/scripts}/init_network/main.go (94%) rename {scripts => test/scripts}/postgres/prover-user.sql (100%) rename {scripts => test/scripts}/postgres/run.sh (100%) mode change 100755 => 100644 create mode 100644 test/scripts/sendForcedBatch/README.md create mode 100644 test/scripts/sendForcedBatch/main.go create mode 100644 test/scripts/send_transfers/main.go create mode 100644 test/scripts/sequenceForcedBatch/README.md create mode 100644 test/scripts/sequenceForcedBatch/main.go create mode 100644 test/scripts/txsender/README.md create mode 100644 test/scripts/txsender/main.go create mode 100644 test/scripts/uniswap/main.go create mode 100644 test/sequencer.keystore create mode 100644 test/vectors/src/state-transition/forced-tx/erc20_0.json create mode 100644 test/vectors/src/state-transition/forced-tx/eth-CallEcrecoverInvalidSignature.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_0.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_1.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_2.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_3.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_4.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_5.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_6.json create mode 100644 test/vectors/src/state-transition/forced-tx/general_7.json create mode 100644 test/vectors/src/state-transition/forced-tx/mynft_0.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_0.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_1.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_2.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_3.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_4.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_5.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_6.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_7.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_8.json create mode 100644 test/vectors/src/state-transition/forced-tx/test-deploy_9.json create mode 100644 test/vectors/src/state-transition/forced-tx/uniswapv2_1.json create mode 100644 test/vectors/src/tx-hash-ethereum/rlp.json create mode 100644 test/vectors/statetransition_v2.go create mode 100644 test/vectors/vectors_v2.go delete mode 100644 tools/genesis/generator.go delete mode 100644 tools/zkevmprovermock/cmd/client.go delete mode 100644 tools/zkevmprovermock/cmd/main.go delete mode 100644 tools/zkevmprovermock/cmd/server.go delete mode 100644 tools/zkevmprovermock/server/executor.go delete mode 100644 tools/zkevmprovermock/server/statedb.go delete mode 100644 tools/zkevmprovermock/testvector/main.go delete mode 100644 tools/zkevmprovermock/testvector/testvector_test.go create mode 100644 version.go create mode 100644 version.mk diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000000..c7c848431c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,31 @@ +--- +name: Report a bug +about: Something with Polygon zkEVM is not working as expected +title: '' +labels: 'type:bug' +assignees: '' +--- + +#### System information + +zkEVM Node version: `v0.0.X-RCXX` +OS & Version: `Windows/Linux/OSX` +Commit hash : (if `develop`) +Network: `Mainnet/Testnet` + +#### Expected behaviour + + +#### Actual behaviour + + +#### Steps to reproduce the behaviour + + +#### Backtrace + +```` +[backtrace] +```` + +When submitting logs: please submit them as text and not screenshots. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 0000000000..aacd885f9e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,17 @@ +--- +name: Request a feature +about: Report a missing feature - e.g. as a step before submitting a PR +title: '' +labels: 'type:feature' +assignees: '' +--- + +# Rationale + +Why should this feature exist? +What are the use-cases? + +# Implementation + +Do you have ideas regarding the implementation of this feature? +Are you willing to implement this feature? \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000000..2d06858d17 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,9 @@ +--- +name: Ask a question +about: Something is unclear +title: '' +labels: 'type:question' +assignees: '' +--- + +This should only be used in very rare cases e.g. if you are not 100% sure if something is a bug or asking a question that leads to improving the documentation. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..3dd480f892 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,76 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "develop", main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "develop" ] + schedule: + - cron: '41 17 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e3ed56774a..5d2d399ac4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,17 +6,18 @@ on: - master - develop - update-external-dependencies + - 'release/**' pull_request: jobs: lint: runs-on: ubuntu-latest steps: - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: - go-version: 1.17.x + go-version: 1.19.x - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Lint run: | make install-linter diff --git a/.github/workflows/ok-to-test.yml b/.github/workflows/ok-to-test.yml deleted file mode 100644 index 8c36b929fc..0000000000 --- a/.github/workflows/ok-to-test.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Ok To Test - -on: - issue_comment: - types: [created] - -jobs: - ok-to-test: - runs-on: ubuntu-latest - if: ${{ github.event.issue.pull_request }} - steps: - - name: Slash Command Dispatch - uses: peter-evans/slash-command-dispatch@v1 - env: - TOKEN: ${{ steps.generate_token.outputs.token }} - with: - token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - reaction-token: ${{ secrets.GITHUB_TOKEN }} - issue-type: pull-request - commands: ok-to-test - named-args: true - permission: write diff --git a/.github/workflows/push-docker-develop.yml b/.github/workflows/push-docker-develop.yml index efb1f16c3d..c3a9a69527 100644 --- a/.github/workflows/push-docker-develop.yml +++ b/.github/workflows/push-docker-develop.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -17,7 +17,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -30,23 +30,3 @@ jobs: push: true tags: | hermeznetwork/zkevm-node:develop - - - name: Check changes in zkevmprovermock - id: zkevmprovermock_changes - uses: dorny/paths-filter@v2 - with: - filters: | - zkevmprovermock: - - 'tools/zkevmprovermock/**' - - - name: Build and push zkevmprovermock - if: steps.zkevmprovermock_changes.outputs.zkevmprovermock == 'true' - id: docker_build_zkevmprovermock - uses: docker/build-push-action@v2 - with: - context: . - file: tools/zkevmprovermock/Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: | - hermeznetwork/zkprover-mock:develop diff --git a/.github/workflows/push-docker-tagged.yml b/.github/workflows/push-docker-tagged.yml new file mode 100644 index 0000000000..402e71e466 --- /dev/null +++ b/.github/workflows/push-docker-tagged.yml @@ -0,0 +1,33 @@ +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' # this action will only run on tags that follow semver + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: | + hermeznetwork/zkevm-node:${{ github.ref_name }} diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml deleted file mode 100644 index b074654feb..0000000000 --- a/.github/workflows/push-docker.yml +++ /dev/null @@ -1,52 +0,0 @@ -on: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - id: docker_build - uses: docker/build-push-action@v2 - with: - platforms: linux/amd64,linux/arm64 - push: true - tags: | - hermeznetwork/zkevm-node:latest - - - name: Check changes in zkevmprovermock - id: zkevmprovermock_changes - uses: dorny/paths-filter@v2 - with: - filters: | - zkevmprovermock: - - 'tools/zkevmprovermock/**' - - - name: Build and push zkevmprovermock - if: steps.zkevmprovermock_changes.outputs.zkevmprovermock == 'true' - id: docker_build_zkevmprovermock - uses: docker/build-push-action@v2 - with: - context: . - file: tools/zkevmprovermock/Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: | - hermeznetwork/zkprover-mock:latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a549002782..22ce39f09d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,30 +1,64 @@ -name: goreleaser +name: release on: push: tags: - - 'v*.*.*' + - 'v[0-9]+.[0-9]+.[0-9]' # this action will only run on tags that follow semver jobs: - goreleaser: + releaser: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.17 + go-version: 1.19 + - name: Get packr - run: go get -u github.com/gobuffalo/packr/v2/packr2 - - name: Prepare - run: git reset --hard + run: go install github.com/gobuffalo/packr/v2/packr2@v2.8.3 + - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2 + uses: goreleaser/goreleaser-action@v4 with: version: latest - args: release --rm-dist + args: release --clean env: - GITHUB_TOKEN: ${{ secrets.TOKEN_RELEASE }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.TOKEN_RELEASE }} + + - name: Get tag + uses: olegtarasov/get-tag@v2.1.2 + id: tagName + + - name: Put testnet and mainnet artifacts into a single zip + run: | + # TESTNET + mkdir -p testnet/config/environments/public + mkdir -p testnet/db/scripts + cp config/environments/public/* testnet/config/environments/public + cp docker-compose.yml testnet + cp db/scripts/init_prover_db.sql testnet/db/scripts + mv testnet/config/environments/public/example.env testnet + sed -i -e "s/image: zkevm-node/image: hermeznetwork\/zkevm-node:$GIT_TAG_NAME/g" testnet/docker-compose.yml + zip -r testnet.zip testnet + # MAINNET + mkdir -p mainnet/config/environments/public + mkdir -p mainnet/db/scripts + cp config/environments/mainnet/* mainnet/config/environments/public + cp docker-compose.yml mainnet + cp db/scripts/init_prover_db.sql mainnet/db/scripts + mv mainnet/config/environments/public/example.env mainnet + sed -i -e "s/image: zkevm-node/image: hermeznetwork\/zkevm-node:$GIT_TAG_NAME/g" mainnet/docker-compose.yml + zip -r mainnet.zip mainnet + + - name: Publish testnet and mainnet zip into release + uses: AButler/upload-release-assets@v2.0 + with: + files: 'testnet.zip;mainnet.zip' + repo-token: ${{ secrets.TOKEN_RELEASE }} + release-tag: ${{ steps.tagName.outputs.tag }} + \ No newline at end of file diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml new file mode 100644 index 0000000000..30c260dbd9 --- /dev/null +++ b/.github/workflows/sonarqube.yml @@ -0,0 +1,22 @@ +name: SonarQube analysis + +on: + push: + branches: + - develop + +jobs: + sonarqube: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + # Disabling shallow clone is recommended for improving relevancy of reporting. + fetch-depth: 0 + + # Triggering SonarQube analysis as results of it are required by Quality Gate check. + - name: SonarQube Scan + uses: sonarsource/sonarqube-scan-action@master + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 9d42621153..8b51456ac1 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -7,92 +7,36 @@ on: - master - develop - update-external-dependencies + - 'release/**' pull_request: - repository_dispatch: - types: [ok-to-test-command] jobs: - trusted-test-e2e: - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository + test-e2e: strategy: + fail-fast: false matrix: - go-version: [ 1.17.x ] + go-version: [ 1.19.x ] goarch: [ "amd64" ] - e2e-group: [ 2 ] + e2e-group: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 - - name: Install Go - uses: actions/setup-go@v1 - with: - go-version: ${{ matrix.go-version }} - env: - GOARCH: ${{ matrix.goarch }} - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Test - run: make test-e2e-group-${{ matrix.e2e-group }} + uses: actions/checkout@v3 - from-fork-test-e2e: - if: - github.event_name == 'repository_dispatch' && - github.event.client_payload.slash_command.sha != '' && - contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha) - strategy: - matrix: - go-version: [ 1.17.x ] - goarch: [ "amd64" ] - e2e-group: [ 2 ] - runs-on: ubuntu-latest - steps: - - name: Fork based /ok-to-test checkout - uses: actions/checkout@v2 - with: - ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge' - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} env: GOARCH: ${{ matrix.goarch }} - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Test - run: CONFIG_MODE="test" make test-e2e-group-${{ matrix.e2e-group }} - # Update check run - - uses: actions/github-script@v5 - id: update-check-run - if: ${{ always() }} - env: - number: ${{ github.event.client_payload.pull_request.number }} - job: ${{ github.job }} - # Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run - conclusion: ${{ job.status }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { data: pull } = await github.rest.pulls.get({ - ...context.repo, - pull_number: process.env.number - }); - const ref = pull.head.sha; - const { data: checks } = await github.rest.checks.listForRef({ - ...context.repo, - ref - }); - const check = checks.check_runs.filter(c => c.name === process.env.job); - const { data: result } = await github.rest.checks.update({ - ...context.repo, - check_run_id: check[0].id, - status: 'completed', - conclusion: process.env.conclusion - }); - return result; + - name: Build Docker + run: make build-docker + + - name: Compile SCs + run: make compile-scs + working-directory: test + + - name: Test + run: make test-e2e-group-${{ matrix.e2e-group }} + working-directory: test diff --git a/.github/workflows/test-from-prover.yml b/.github/workflows/test-from-prover.yml index c152f017e9..ca917668a4 100644 --- a/.github/workflows/test-from-prover.yml +++ b/.github/workflows/test-from-prover.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: - go-version: [ 1.17.x ] + go-version: [ 1.19.x ] goarch: [ "amd64" ] e2e-group: [ 2 ] @@ -28,17 +28,25 @@ jobs: repository: 0xPolygonHermez/zkevm-node - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} env: GOARCH: ${{ matrix.goarch }} - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build Docker + run: make build-docker + + - name: Compile SCs + run: make compile-scs + working-directory: test + - name: Test run: make test-full-non-e2e + working-directory: test diff --git a/.github/workflows/test-full-non-e2e.yml b/.github/workflows/test-full-non-e2e.yml index 615991fc44..723726cb8c 100644 --- a/.github/workflows/test-full-non-e2e.yml +++ b/.github/workflows/test-full-non-e2e.yml @@ -7,93 +7,33 @@ on: - master - develop - update-external-dependencies + - 'release/**' pull_request: - repository_dispatch: - types: [ok-to-test-command] jobs: - trusted-test-full-non-e2e: - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository + test-full-non-e2e: strategy: matrix: - go-version: [ 1.17.x ] + go-version: [ 1.19.x ] goarch: [ "amd64" ] runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 - - name: Install Go - uses: actions/setup-go@v1 - with: - go-version: ${{ matrix.go-version }} - env: - GOARCH: ${{ matrix.goarch }} - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Test - env: - ZKPROVER_URI: 127.0.0.1 - run: make test-full-non-e2e + uses: actions/checkout@v3 - from-fork-test-full-non-e2e: - if: - github.event_name == 'repository_dispatch' && - github.event.client_payload.slash_command.sha != '' && - contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha) - strategy: - matrix: - go-version: [ 1.17.x ] - goarch: [ "amd64" ] - runs-on: ubuntu-latest - steps: - - name: Fork based /ok-to-test checkout - uses: actions/checkout@v2 - with: - ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge' - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} env: GOARCH: ${{ matrix.goarch }} - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Compile SCs + run: make compile-scs + working-directory: test + - name: Test env: ZKPROVER_URI: 127.0.0.1 run: make test-full-non-e2e - - # Update check run - - uses: actions/github-script@v5 - id: update-check-run - if: ${{ always() }} - env: - number: ${{ github.event.client_payload.pull_request.number }} - job: ${{ github.job }} - conclusion: ${{ job.status }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { data: pull } = await github.rest.pulls.get({ - ...context.repo, - pull_number: process.env.number - }); - const ref = pull.head.sha; - const { data: checks } = await github.rest.checks.listForRef({ - ...context.repo, - ref - }); - const check = checks.check_runs.filter(c => c.name === process.env.job); - const { data: result } = await github.rest.checks.update({ - ...context.repo, - check_run_id: check[0].id, - status: 'completed', - conclusion: process.env.conclusion - }); - return result; + working-directory: test diff --git a/.github/workflows/updatedeps.yml b/.github/workflows/updatedeps.yml index 0c913380c1..7f0896525c 100644 --- a/.github/workflows/updatedeps.yml +++ b/.github/workflows/updatedeps.yml @@ -9,25 +9,30 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 + - name: Install Go - uses: actions/setup-go@v1 + uses: actions/setup-go@v3 with: - go-version: "1.17.x" + go-version: "1.19.x" env: GOARCH: "amd64" + - name: Install Protoc uses: arduino/setup-protoc@v1 + - name: Install protoc-gen-go run: | go install github.com/golang/protobuf/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + - name: Update deps env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} run: make update-external-dependencies + - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: diff --git a/.gitignore b/.gitignore index 9786e3e7c1..f58fd80ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,13 @@ /test/vectors/src/**/*sh /test/vectors/src/package.json -/test/contracts/**/*.abi -/test/contracts/**/*.bin /test/contracts/bin/**/*.bin /test/contracts/bin/**/*.abi **/.DS_Store -.vscode \ No newline at end of file +.vscode +.idea/ +.env +out.dat + +cmd/__debug_bin \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml index 87d6e0e5f2..2891a8bad5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,11 @@ --- run: timeout: 5m + skip-dirs: + - state/runtime/fakevm + - state/runtime/instrumentation + - test + - ci linters: enable: diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000000..21264f08be --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,17 @@ +# .goreleaser.yaml +builds: +- main: ./cmd/ + goos: + - linux + - darwin + goarch: + - amd64 + - arm64 + env: + - CGO_ENABLED=0 +release: + # If set to auto, will mark the release as not ready for production + # in case there is an indicator for this in the tag e.g. v1.0.0-rc1 + # If set to true, will mark the release as not ready for production. + # Default is false. + prerelease: true diff --git a/Dockerfile b/Dockerfile index fae008fde5..70785db41b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,5 @@ # CONTAINER FOR BUILDING BINARY -FROM golang:1.17 AS build - -ENV CGO_ENABLED=0 +FROM golang:1.19 AS build # INSTALL DEPENDENCIES RUN go install github.com/gobuffalo/packr/v2/packr2@v2.8.3 @@ -16,6 +14,6 @@ RUN cd /src && make build # CONTAINER FOR RUNNING BINARY FROM alpine:3.16.0 COPY --from=build /src/dist/zkevm-node /app/zkevm-node -COPY --from=build /src/config/config.local.toml /app/config.local.toml +COPY --from=build /src/config/environments/public/public.node.config.toml /app/example.config.toml EXPOSE 8123 -CMD ["/bin/sh", "-c", "/app/zkevm-node run"] \ No newline at end of file +CMD ["/bin/sh", "-c", "/app/zkevm-node run"] diff --git a/LICENSE b/LICENSE index 94a9ed024d..6b7dcd6383 100644 --- a/LICENSE +++ b/LICENSE @@ -1,23 +1,38 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 +Polygon zkEVM Mainnet Beta +Copyright (C) 2023 Catenable AG - Copyright (C) 2007 Free Software Foundation, Inc. + This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + + This program 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 Affero General Public +License for more details. + + You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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. Preamble - The GNU General Public License is a free, copyleft license for -software and other kinds of works. + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to +our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. +software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you @@ -26,44 +41,34 @@ them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. The precise terms and conditions for copying, distribution and modification follow. @@ -72,7 +77,7 @@ modification follow. 0. Definitions. - "This License" refers to version 3 of the GNU General Public License. + "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. @@ -549,35 +554,45 @@ to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. - 13. Use with the GNU Affero General Public License. + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single +under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of -the GNU 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 +the GNU Affero 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 -Program specifies that a certain numbered version of the GNU General +Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published +GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's +versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. @@ -619,56 +634,3 @@ Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Makefile b/Makefile index 737d88e1f1..285baf228d 100644 --- a/Makefile +++ b/Makefile @@ -1,92 +1,28 @@ -DOCKERCOMPOSE := docker-compose -f docker-compose.yml -DOCKERCOMPOSEAPPSEQ := zkevm-sequencer -DOCKERCOMPOSEAPPAGG := zkevm-aggregator -DOCKERCOMPOSEAPPRPC := zkevm-json-rpc -DOCKERCOMPOSEAPPSYNC := zkevm-sync -DOCKERCOMPOSEAPPBROADCAST := zkevm-broadcast -DOCKERCOMPOSESTATEDB := zkevm-state-db -DOCKERCOMPOSEPOOLDB := zkevm-pool-db -DOCKERCOMPOSERPCDB := zkevm-rpc-db -DOCKERCOMPOSENETWORK := zkevm-mock-l1-network -DOCKERCOMPOSEEXPLORERL1 := zkevm-explorer-l1 -DOCKERCOMPOSEEXPLORERL1DB := zkevm-explorer-l1-db -DOCKERCOMPOSEEXPLORERL2 := zkevm-explorer-l2 -DOCKERCOMPOSEEXPLORERL2DB := zkevm-explorer-l2-db -DOCKERCOMPOSEEXPLORERRPC := zkevm-explorer-json-rpc -DOCKERCOMPOSEZKPROVER := zkevm-prover -DOCKERCOMPOSEZKPROVERMOCK := zkprover-mock -DOCKERCOMPOSEPERMISSIONLESSDB := zkevm-permissionless-db -DOCKERCOMPOSEPERMISSIONLESSNODE := zkevm-permissionless-node -DOCKERCOMPOSENODEAPPROVE := zkevm-approve +include version.mk -RUNSTATEDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSESTATEDB) -RUNPOOLDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPOOLDB) -RUNRPCDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSERPCDB) -RUNSEQUENCER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPSEQ) -RUNAGGREGATOR := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPAGG) -RUNJSONRPC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPRPC) -RUNSYNC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPSYNC) -RUNBROADCAST := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPBROADCAST) - -RUNL1NETWORK := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSENETWORK) -RUNEXPLORERL1 := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL1) -RUNEXPLORERL1DB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL1DB) -RUNEXPLORERL2 := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL2) -RUNEXPLORERL2DB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL2DB) -RUNEXPLORERJSONRPC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERRPC) -RUNZKPROVER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEZKPROVER) -RUNZKPROVERMOCK := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEZKPROVERMOCK) - -RUNPERMISSIONLESSDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPERMISSIONLESSDB) -RUNPERMISSIONLESSNODE := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPERMISSIONLESSNODE) - -RUNAPPROVE := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSENODEAPPROVE) - -RUN := $(DOCKERCOMPOSE) up -d - -STOPSTATEDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSESTATEDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSESTATEDB) -STOPPOOLDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPOOLDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPOOLDB) -STOPRPCDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSERPCDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSERPCDB) -STOPSEQUENCER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPSEQ) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPSEQ) -STOPAGGREGATOR := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPAGG) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPAGG) -STOPJSONRPC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPRPC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPRPC) -STOPSYNC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPSYNC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPSYNC) -STOPBROADCAST := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPBROADCAST) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPBROADCAST) - -STOPNETWORK := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSENETWORK) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSENETWORK) -STOPEXPLORERL1 := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL1) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL1) -STOPEXPLORERL1DB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL1DB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL1DB) -STOPEXPLORERL2 := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL2) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL2) -STOPEXPLORERL2DB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL2DB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL2DB) -STOPEXPLORERRPC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERRPC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERRPC) -STOPZKPROVER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEZKPROVER) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEZKPROVER) -STOPZKPROVERMOCK := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEZKPROVERMOCK) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEZKPROVERMOCK) - -STOPPERMISSIONLESSDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPERMISSIONLESSDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPERMISSIONLESSDB) -STOPPERMISSIONLESSNODE := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPERMISSIONLESSNODE) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPERMISSIONLESSNODE) - -STOPAPPROVE := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSENODEAPPROVE) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSENODEAPPROVE) - -STOP := $(DOCKERCOMPOSE) down --remove-orphans - -VERSION := $(shell git describe --tags --always) -COMMIT := $(shell git rev-parse --short HEAD) -DATE := $(shell date +%Y-%m-%dT%H:%M:%S%z) -LDFLAGS := -ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE)" +ARCH := $(shell arch) +ifeq ($(ARCH),x86_64) + ARCH = amd64 +else + ifeq ($(ARCH),aarch64) + ARCH = arm64 + endif +endif GOBASE := $(shell pwd) GOBIN := $(GOBASE)/dist -GOENVVARS := GOBIN=$(GOBIN) +GOENVVARS := GOBIN=$(GOBIN) CGO_ENABLED=0 GOOS=linux GOARCH=$(ARCH) GOBINARY := zkevm-node GOCMD := $(GOBASE)/cmd -LINT := $$(go env GOPATH)/bin/golangci-lint run - -BUILD := $(GOENVVARS) go build $(LDFLAGS) -o $(GOBIN)/$(GOBINARY) $(GOCMD) +LDFLAGS += -X 'github.com/0xPolygonHermez/zkevm-node.Version=$(VERSION)' +LDFLAGS += -X 'github.com/0xPolygonHermez/zkevm-node.GitRev=$(GITREV)' +LDFLAGS += -X 'github.com/0xPolygonHermez/zkevm-node.GitBranch=$(GITBRANCH)' +LDFLAGS += -X 'github.com/0xPolygonHermez/zkevm-node.BuildDate=$(DATE)' .PHONY: build build: ## Builds the binary locally into ./dist - $(BUILD) + $(GOENVVARS) go build -ldflags "all=$(LDFLAGS)" -o $(GOBIN)/$(GOBINARY) $(GOCMD) .PHONY: build-docker build-docker: ## Builds a docker image with the node binary @@ -96,292 +32,41 @@ build-docker: ## Builds a docker image with the node binary build-docker-nc: ## Builds a docker image with the node binary - but without build cache docker build --no-cache=true -t zkevm-node -f ./Dockerfile . -.PHONY: test -test: compile-scs ## Runs only short tests without checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(STOPZKPROVER) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB) - $(RUNZKPROVER); sleep 5 - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB) && $(STOPZKPROVER)' EXIT; go test -short -race -p 1 ./... - -.PHONY: test-full -test-full: build-docker compile-scs ## Runs all tests checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(STOPZKPROVER) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB) - $(RUNZKPROVER); sleep 5 - $(RUNZKPROVERMOCK) - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB) && $(STOPZKPROVER) && $(STOPZKPROVERMOCK)' EXIT; MallocNanoZone=0 go test -race -v -p 1 -timeout 1200s `go list ./... | grep -v \/ci\/e2e-group` - -.PHONY: test-full-non-e2e -test-full-non-e2e: build-docker compile-scs ## Runs non-e2e tests checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(STOPZKPROVER) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB) - $(RUNZKPROVER); sleep 5 - $(RUNZKPROVERMOCK) +.PHONY: run-rpc +run-rpc: ## Runs all the services need to run a local zkEMV RPC node + docker-compose up -d zkevm-state-db zkevm-pool-db sleep 2 - $(RUNL1NETWORK) - sleep 15 - docker logs $(DOCKERCOMPOSEZKPROVER) - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB) && $(STOPZKPROVER) && $(STOPZKPROVERMOCK) && $(STOPNETWORK)' EXIT; MallocNanoZone=0 go test -short -race -p 1 -timeout 60s ./... - -.PHONY: test-e2e-group-1 -test-e2e-group-1: build-docker compile-scs ## Runs group 1 e2e tests checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB); sleep 5 - $(RUNZKPROVER) - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB) && $(STOPZKPROVER)' EXIT; MallocNanoZone=0 go test -race -v -p 1 -timeout 600s ./ci/e2e-group1/... - -.PHONY: test-e2e-group-2 -test-e2e-group-2: build-docker compile-scs ## Runs group 2 e2e tests checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(STOPZKPROVER) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB); sleep 5 - ${RUNL1NETWORK} - CONFIG_MODE="test" $(RUNZKPROVER) - docker ps -a - docker logs $(DOCKERCOMPOSEZKPROVER) - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB) && $(STOPZKPROVER)' EXIT; MallocNanoZone=0 go test -race -v -p 1 -timeout 600s ./ci/e2e-group2/... + docker-compose up -d zkevm-prover + sleep 5 + docker-compose up -d zkevm-sync + sleep 2 + docker-compose up -d zkevm-rpc -.PHONY: test-e2e-group-3 -test-e2e-group-3: build-docker compile-scs ## Runs group 3 e2e tests checking race conditions - export CONFIG_MODE="test" - $(STOPSTATEDB) - $(STOPPOOLDB) - $(STOPRPCDB) - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB); sleep 5 - $(RUNZKPROVER); sleep 2 - trap '$(STOPSTATEDB) && $(STOPPOOLDB) && $(STOPRPCDB)' EXIT; MallocNanoZone=0 go test -race -v -p 1 -timeout 600s ./ci/e2e-group3/... +.PHONY: stop +stop: ## Stops all services + docker-compose down .PHONY: install-linter install-linter: ## Installs the linter - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.46.2 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.52.2 .PHONY: lint lint: ## Runs the linter - $(LINT) - -.PHONY: check -check: stop lint build build-docker test-full-non-e2e test-e2e-group-2 ## lint, build and essential tests - -.PHONY: validate -validate: lint build test-full ## lint, build, unit and e2e tests - -.PHONY: run-db -run-db: ## Runs the node database - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB) - -.PHONY: stop-db -stop-db: ## Stops the node database - $(STOPRPCDB) - $(STOPPOOLDB) - $(STOPSTATEDB) - -.PHONY: run-node -run-node: ## Runs the node - $(RUNSYNC) - $(RUNSEQUENCER) - $(RUNAGGREGATOR) - $(RUNJSONRPC) - -.PHONY: stop-node -stop-node: ## Stops the node - $(STOPSEQUENCER) - $(STOPJSONRPC) - $(STOPAGGREGATOR) - $(STOPSYNC) - -.PHONY: run-network -run-network: ## Runs the l1 network - $(RUNL1NETWORK) - -.PHONY: stop-network -stop-network: ## Stops the l1 network - $(STOPNETWORK) - -.PHONY: run-zkprover -run-zkprover: ## Runs zkprover - $(RUNZKPROVER) - -.PHONY: stop-zkprover -stop-zkprover: ## Stops zkprover - $(STOPZKPROVER) - -.PHONY: run-zkprover-mock -run-zkprover-mock: ## Runs zkprover-mock - $(RUNZKPROVERMOCK) - -.PHONY: stop-zkprover-mock -stop-zkprover-mock: ## Stops zkprover-mock - $(STOPZKPROVERMOCK) - -.PHONY: run-explorer -run-explorer: ## Runs the explorer - $(RUNEXPLORERL1DB) - $(RUNEXPLORERL2DB) - $(RUNEXPLORERJSONRPC) - $(RUNEXPLORERL1) - $(RUNEXPLORERL2) - -.PHONY: stop-explorer -stop-explorer: ## Stops the explorer - $(STOPEXPLORERL2) - $(STOPEXPLORERL1) - $(STOPEXPLORERRPC) - $(STOPEXPLORERL2DB) - $(STOPEXPLORERL1DB) + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/golangci-lint run -.PHONY: run-explorer-db -run-explorer-db: ## Runs the explorer database - $(RUNEXPLORERL1DB) - $(RUNEXPLORERL2DB) - -.PHONY: stop-explorer-db -stop-explorer-db: ## Stops the explorer database - $(STOPEXPLORERL2DB) - $(STOPEXPLORERL1DB) - -.PHONY: run -run: ## Runs all the services - $(RUNSTATEDB) - $(RUNPOOLDB) - $(RUNRPCDB) - $(RUNL1NETWORK) - sleep 2 - $(RUNZKPROVER) - sleep 5 - $(RUNSEQUENCER) - $(RUNAGGREGATOR) - $(RUNJSONRPC) - $(RUNSYNC) - -.PHONY: run-broadcast -run-broadcast: ## Runs the broadcast service - $(RUNBROADCAST) - -run-seq: - $(RUNSEQUENCER) - -.PHONY: stop-broadcast -stop-broadcast: ## Stops the broadcast service - $(STOPBROADCAST) - -.PHONY: run-permissionless -run-permissionless: ## Runs the permissionless node - $(RUNPERMISSIONLESSDB) - $(RUNPERMISSIONLESSNODE) - -.PHONY: stop-permissionless -stop-permissionless: ## Stops the permissionless node - $(STOPPERMISSIONLESSNODE) - $(STOPPERMISSIONLESSDB) - -.PHONY: run-approve-matic -run-approve-matic: ## Runs approve in node container - $(RUNAPPROVE) - -.PHONY: stop-approve-matic -stop-approve-matic: ## Stops approve in node container - $(STOPAPPROVE) - -#.PHONY: init-network -#init-network: ## Initializes the network -# go run ./scripts/init_network/main.go . - -.PHONY: deploy-sc -deploy-sc: ## deploys some examples of transactions and smart contracts - go run ./scripts/deploy_sc/main.go . - -.PHONY: deploy-uniswap -deploy-uniswap: ## deploy the uniswap environment to the network - go run ./scripts/uniswap/main.go . - -.PHONY: stop -stop: ## Stops all services - $(STOP) - -.PHONY: restart -restart: stop run ## Executes `make stop` and `make run` commands - -.PHONY: run-db-scripts -run-db-scripts: ## Executes scripts on the db after it has been initialized, potentially using info from the environment - ./scripts/postgres/run.sh +.PHONY: update-external-dependencies +update-external-dependencies: ## Updates external dependencies like images, test vectors or proto files + go run ./scripts/cmd/... updatedeps .PHONY: install-git-hooks install-git-hooks: ## Moves hook files to the .git/hooks directory cp .github/hooks/* .git/hooks -.PHONY: generate-mocks -generate-mocks: ## Generates mocks for the tests, using mockery tool - mockery --name=storageInterface --dir=jsonrpc --output=jsonrpc --outpkg=jsonrpc --inpackage --structname=storageMock --filename=mock_storage_test.go - mockery --name=jsonRPCTxPool --dir=jsonrpc --output=jsonrpc --outpkg=jsonrpc --inpackage --structname=poolMock --filename=mock_pool_test.go - mockery --name=gasPriceEstimator --dir=jsonrpc --output=jsonrpc --outpkg=jsonrpc --inpackage --structname=gasPriceEstimatorMock --filename=mock_gasPriceEstimator_test.go - mockery --name=stateInterface --dir=jsonrpc --output=jsonrpc --outpkg=jsonrpc --inpackage --structname=stateMock --filename=mock_state_test.go - mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=jsonrpc --outpkg=jsonrpc --structname=dbTxMock --filename=mock_dbtx_test.go - - mockery --name=txManager --dir=sequencer --output=sequencer/mocks --outpkg=mocks --structname=TxmanagerMock --filename=mock_txmanager.go - mockery --name=etherman --dir=sequencer --output=sequencer/mocks --outpkg=mocks --structname=EthermanMock --filename=mock_etherman.go - mockery --name=etherman --dir=sequencer/profitabilitychecker --output=sequencer/profitabilitychecker/mocks --outpkg=mocks --structname=EthermanMock --filename=mock_etherman.go - mockery --name=stateInterface --dir=sequencer/broadcast --output=sequencer/broadcast/mocks --outpkg=mocks --structname=StateMock --filename=mock_state.go - - mockery --name=ethermanInterface --dir=synchronizer --output=synchronizer --outpkg=synchronizer --structname=ethermanMock --filename=mock_etherman.go - mockery --name=stateInterface --dir=synchronizer --output=synchronizer --outpkg=synchronizer --structname=stateMock --filename=mock_state.go - mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=synchronizer --outpkg=synchronizer --structname=dbTxMock --filename=mock_dbtx.go - - ## mocks for the aggregator tests - mockery --name=stateInterface --dir=aggregator --output=aggregator/mocks --outpkg=mocks --structname=StateMock --filename=mock_state.go - mockery --name=proverClientInterface --dir=aggregator --output=aggregator/mocks --outpkg=mocks --structname=ProverClientMock --filename=mock_proverclient.go - mockery --name=etherman --dir=aggregator --output=aggregator/mocks --outpkg=mocks --structname=Etherman --filename=mock_etherman.go - mockery --name=ethTxManager --dir=aggregator --output=aggregator/mocks --outpkg=mocks --structname=EthTxManager --filename=mock_ethtxmanager.go - .PHONY: generate-code-from-proto generate-code-from-proto: ## Generates code from proto files cd proto/src/proto/statedb/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../merkletree/pb --go-grpc_out=../../../../../merkletree/pb --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative statedb.proto - cd proto/src/proto/zkprover/v1 && protoc --proto_path=. --go_out=../../../../../proverclient/pb --go-grpc_out=../../../../../proverclient/pb --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative zk_prover.proto cd proto/src/proto/executor/v1 && protoc --proto_path=. --go_out=../../../../../state/runtime/executor/pb --go-grpc_out=../../../../../state/runtime/executor/pb --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative executor.proto - cd proto/src/proto/broadcast/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../sequencer/broadcast/pb --go-grpc_out=../../../../../sequencer/broadcast/pb --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative broadcast.proto - -.PHONY: update-external-dependencies -update-external-dependencies: ## Updates external dependencies like images, test vectors or proto files - go run ./scripts/cmd/... updatedeps - -.PHONY: run-benchmarks -run-benchmarks: run-db ## Runs benchmars - go test -bench=. ./state/tree - -.PHONY: compile-scs -compile-scs: ## Compiles smart contracts, configuration in test/contracts/index.yaml - go run ./scripts/cmd... compilesc --input ./test/contracts + cd proto/src/proto/aggregator/v1 && protoc --proto_path=. --proto_path=../../../../include --go_out=../../../../../aggregator/pb --go-grpc_out=../../../../../aggregator/pb --go-grpc_opt=paths=source_relative --go_opt=paths=source_relative aggregator.proto ## Help display. ## Pulls comments from beside commands and prints a nicely formatted diff --git a/README.md b/README.md index 498d57adf0..37cdcb7901 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ zkEVM Node is a Go implementation of a node that operates the Polygon zkEVM Netw ## About the Polygon zkEVM network -Since this is an implementation of a protocol it's fundamental to understand it, [here](https://docs.hermez.io/) you can find the specification of the protocol. +Since this is an implementation of a protocol it's fundamental to understand it, [here](https://zkevm.polygon.technology/docs/zknode/zknode-overview) you can find the specification of the protocol. Glossary: @@ -34,11 +34,10 @@ The diagram represents the main components of the software and how they interact - (JSON) RPC: an interface that allows users (metamask, etherscan, ...) to interact with the node. Fully compatible with Ethereum RPC + some extra endpoints specifics of the network. It interacts with the `state` to get data and process transactions and with the `pool` to store transactions - Pool: DB that stores transactions by the `RPC` to be selected/discarded by the `sequencer` later on -- Trusted Sequencer: get transactions from the `pool`, check if they are valid by processing them using the `state`, and create sequences. Once transactions are added into the state, they are immediately available to the `broadcast` service. Sequences are sent to L1 using the `etherman` -- Broadcast: API used by the `synchronizer` of nodes that are not the `trusted sequencer` to synchronize the trusted state +- Trusted Sequencer: get transactions from the `pool`, check if they are valid by processing them using the `state`, and create sequences. Once transactions are added into the state, they are immediately available through the `rpc`. Sequences are sent to L1 using the `etherman` - Permissionless Sequencer: *coming soon* - Etherman: abstraction that implements the needed methods to interact with the Ethereum network and the relevant smart contracts. -- Synchronizer: Updates the `state` by fetching data from Ethereum through the `etherman`. If the node is not a `trusted sequencer` it also updates the state with the data fetched from the `broadcast` of the `trusted sequencer`. It also detects and handles reorgs that can happen if the `trusted sequencer` sends different data in the broadcast vs the sequences sent to L1 (trusted vs virtual state) +- Synchronizer: Updates the `state` by fetching data from Ethereum through the `etherman`. If the node is not a `trusted sequencer` it also updates the state with the data fetched from the `rpc` of the `trusted sequencer`. It also detects and handles reorgs that can happen if the `trusted sequencer` sends different data in the rpc vs the sequences sent to L1 (trusted vs virtual state) - State: Responsible for managing the state data (batches, blocks, transactions, ...) that is stored on the `state SB`. It also handles the integration with the `executor` and the `Merkletree` service - State DB: persistence layer for the state data (except the Merkletree that is handled by the `Merkletree` service) - Aggregator: consolidates batches by generating ZKPs (Zero Knowledge proofs). To do so it gathers the necessary data that the `prover` needs as input through the `state` and sends a request to it. Once the proof is generated it's sent to Ethereum through the `etherman` @@ -64,6 +63,9 @@ Required services and components: There must be only one synchronizer, and it's recommended that it has exclusive access to an executor instance, although it's not necessary. This role can perfectly be run in a single instance, however, the JSON RPC and executor services can benefit from running in multiple instances, if the performance decreases due to the number of requests received +- [`zkEVM RPC endpoints`](./docs/json-rpc-endpoints.md) +- [`zkEVM RPC Custom endpoints documentation`](./docs/zkEVM-custom-endpoints.md) + ### Trusted sequencer This role can only be performed by a single entity. This is enforced in the smart contract, as the related methods of the trusted sequencer can only be performed by the owner of a particular private key. @@ -73,7 +75,6 @@ Required services and components: - JSON RPC: can run in a separated instance, and can have multiple instances - Sequencer & Synchronizer: single instance that needs to run together - Executor & Merkletree: service that can run on a separate instance -- Broadcast: can run on a separate instance - Pool DB: Postgres SQL that can be run in a separate instance - State DB: Postgres SQL that can be run in a separate instance @@ -104,12 +105,12 @@ It's recommended to use `make` for building, and testing the code, ... Run `make ## Running the node -- [Running localy](docs/running_local.md) +- [Running locally](docs/running_local.md) - [Running on production](docs/production-setup.md) ### Requirements -- Go 1.17 +- Go 1.19 - Docker - Docker Compose - Make @@ -119,6 +120,4 @@ It's recommended to use `make` for building, and testing the code, ... Run `make Before opening a pull request, please read this [guide](CONTRIBUTING.md) -## Disclaimer -This code has not yet been audited, and should not be used in any production systems. diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go index 1117712971..93420738f8 100644 --- a/aggregator/aggregator.go +++ b/aggregator/aggregator.go @@ -2,317 +2,974 @@ package aggregator import ( "context" - "encoding/binary" + "encoding/json" "errors" "fmt" "math/big" + "net" + "strconv" + "strings" + "sync" "time" + "unicode" + "github.com/0xPolygonHermez/zkevm-node/aggregator/metrics" + "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" "github.com/0xPolygonHermez/zkevm-node/aggregator/prover" + "github.com/0xPolygonHermez/zkevm-node/config/types" "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/hex" + ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" - "github.com/iden3/go-iden3-crypto/keccak256" + "github.com/jackc/pgx/v4" "google.golang.org/grpc" + grpchealth "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/peer" ) +const ( + mockedStateRoot = "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9" + mockedLocalExitRoot = "0x17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e" + + ethTxManagerOwner = "aggregator" + monitoredIDFormat = "proof-from-%v-to-%v" +) + +type finalProofMsg struct { + proverName string + proverID string + recursiveProof *state.Proof + finalProof *pb.FinalProof +} + // Aggregator represents an aggregator type Aggregator struct { + pb.UnimplementedAggregatorServiceServer + cfg Config - State stateInterface - EthTxManager ethTxManager - Ethman etherman - ProverClients []proverClientInterface - ProfitabilityChecker aggregatorTxProfitabilityChecker + State stateInterface + EthTxManager ethTxManager + Ethman etherman + ProfitabilityChecker aggregatorTxProfitabilityChecker + TimeSendFinalProof time.Time + TimeCleanupLockedProofs types.Duration + StateDBMutex *sync.Mutex + TimeSendFinalProofMutex *sync.RWMutex + + finalProof chan finalProofMsg + verifyingProof bool + + srv *grpc.Server + ctx context.Context + exit context.CancelFunc } -// NewAggregator creates a new aggregator -func NewAggregator( +// New creates a new aggregator. +func New( cfg Config, - state stateInterface, + stateInterface stateInterface, ethTxManager ethTxManager, etherman etherman, - grpcClientConns []*grpc.ClientConn, ) (Aggregator, error) { var profitabilityChecker aggregatorTxProfitabilityChecker switch cfg.TxProfitabilityCheckerType { case ProfitabilityBase: - profitabilityChecker = NewTxProfitabilityCheckerBase(state, cfg.IntervalAfterWhichBatchConsolidateAnyway.Duration, cfg.TxProfitabilityMinReward.Int) + profitabilityChecker = NewTxProfitabilityCheckerBase(stateInterface, cfg.IntervalAfterWhichBatchConsolidateAnyway.Duration, cfg.TxProfitabilityMinReward.Int) case ProfitabilityAcceptAll: - profitabilityChecker = NewTxProfitabilityCheckerAcceptAll(state, cfg.IntervalAfterWhichBatchConsolidateAnyway.Duration) - } - - proverClients := make([]proverClientInterface, 0, len(cfg.ProverURIs)) - - for _, proverURI := range cfg.ProverURIs { - proverClient := prover.NewClient(proverURI, cfg.IntervalFrequencyToGetProofGenerationState) - proverClients = append(proverClients, proverClient) - grpcClientConns = append(grpcClientConns, proverClient.Prover.Conn) - log.Infof("Connected to prover %v", proverURI) + profitabilityChecker = NewTxProfitabilityCheckerAcceptAll(stateInterface, cfg.IntervalAfterWhichBatchConsolidateAnyway.Duration) } a := Aggregator{ cfg: cfg, - State: state, - EthTxManager: ethTxManager, - Ethman: etherman, - ProverClients: proverClients, - ProfitabilityChecker: profitabilityChecker, + State: stateInterface, + EthTxManager: ethTxManager, + Ethman: etherman, + ProfitabilityChecker: profitabilityChecker, + StateDBMutex: &sync.Mutex{}, + TimeSendFinalProofMutex: &sync.RWMutex{}, + TimeCleanupLockedProofs: cfg.CleanupLockedProofsInterval, + + finalProof: make(chan finalProofMsg), } return a, nil } // Start starts the aggregator -func (a *Aggregator) Start(ctx context.Context) { - // define those vars here, bcs it can be used in case <-a.ctx.Done() - tickerVerifyBatch := time.NewTicker(a.cfg.IntervalToConsolidateState.Duration) - tickerSendVerifiedBatch := time.NewTicker(a.cfg.IntervalToConsolidateState.Duration) - defer tickerVerifyBatch.Stop() - defer tickerSendVerifiedBatch.Stop() - - // Delete proofs that where being generated during last reboot +func (a *Aggregator) Start(ctx context.Context) error { + var cancel context.CancelFunc + if ctx == nil { + ctx = context.Background() + } + ctx, cancel = context.WithCancel(ctx) + a.ctx = ctx + a.exit = cancel + + metrics.Register() + + // process monitored batch verifications before starting + a.EthTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) { + a.handleMonitoredTxResult(result) + }, nil) + + // Delete ungenerated recursive proofs err := a.State.DeleteUngeneratedProofs(ctx, nil) - if err != nil && err != state.ErrNotFound { - log.Warn("error deleting work in progress proofs from state") + if err != nil { + return fmt.Errorf("failed to initialize proofs cache %w", err) } - for i := 0; i < len(a.ProverClients); i++ { - go func() { - for { - a.tryVerifyBatch(ctx, tickerVerifyBatch) - } - }() - time.Sleep(time.Second) + address := fmt.Sprintf("%s:%d", a.cfg.Host, a.cfg.Port) + lis, err := net.Listen("tcp", address) + if err != nil { + log.Fatalf("Failed to listen: %v", err) } + a.srv = grpc.NewServer() + pb.RegisterAggregatorServiceServer(a.srv, a) + + healthService := newHealthChecker() + grpchealth.RegisterHealthServer(a.srv, healthService) + go func() { - for { - a.tryToSendVerifiedBatch(ctx, tickerSendVerifiedBatch) + log.Infof("Server listening on port %d", a.cfg.Port) + if err := a.srv.Serve(lis); err != nil { + a.exit() + log.Fatalf("Failed to serve: %v", err) } }() - // Wait until context is done + + a.resetVerifyProofTime() + + go a.cleanupLockedProofs() + go a.sendFinalProof() + <-ctx.Done() + return ctx.Err() +} + +// Stop stops the Aggregator server. +func (a *Aggregator) Stop() { + a.exit() + a.srv.Stop() +} + +// Channel implements the bi-directional communication channel between the +// Prover client and the Aggregator server. +func (a *Aggregator) Channel(stream pb.AggregatorService_ChannelServer) error { + metrics.ConnectedProver() + defer metrics.DisconnectedProver() + + ctx := stream.Context() + var proverAddr net.Addr + p, ok := peer.FromContext(ctx) + if ok { + proverAddr = p.Addr + } + prover, err := prover.New(stream, proverAddr, a.cfg.ProofStatePollingInterval) + if err != nil { + return err + } + + log := log.WithFields( + "prover", prover.Name(), + "proverId", prover.ID(), + "proverAddr", prover.Addr(), + ) + log.Info("Establishing stream connection with prover") + + // Check if prover supports the required Fork ID + if !prover.SupportsForkID(a.cfg.ForkId) { + err := errors.New("prover does not support required fork ID") + log.Warn(FirstToUpper(err.Error())) + return err + } + + for { + select { + case <-a.ctx.Done(): + // server disconnected + return a.ctx.Err() + case <-ctx.Done(): + // client disconnected + return ctx.Err() + + default: + isIdle, err := prover.IsIdle() + if err != nil { + log.Errorf("Failed to check if prover is idle: %v", err) + time.Sleep(a.cfg.RetryTime.Duration) + continue + } + if !isIdle { + log.Debug("Prover is not idle") + time.Sleep(a.cfg.RetryTime.Duration) + continue + } + + _, err = a.tryBuildFinalProof(ctx, prover, nil) + if err != nil { + log.Errorf("Error checking proofs to verify: %v", err) + } + + proofGenerated, err := a.tryAggregateProofs(ctx, prover) + if err != nil { + log.Errorf("Error trying to aggregate proofs: %v", err) + } + if !proofGenerated { + proofGenerated, err = a.tryGenerateBatchProof(ctx, prover) + if err != nil { + log.Errorf("Error trying to generate proof: %v", err) + } + } + if !proofGenerated { + // if no proof was generated (aggregated or batch) wait some time before retry + time.Sleep(a.cfg.RetryTime.Duration) + } // if proof was generated we retry immediately as probably we have more proofs to process + } + } +} + +// This function waits to receive a final proof from a prover. Once it receives +// the proof, it performs these steps in order: +// - send the final proof to L1 +// - wait for the synchronizer to catch up +// - clean up the cache of recursive proofs +func (a *Aggregator) sendFinalProof() { + for { + select { + case <-a.ctx.Done(): + return + case msg := <-a.finalProof: + ctx := a.ctx + proof := msg.recursiveProof + + log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal)) + log.Info("Verifying final proof with ethereum smart contract") + + a.startProofVerification() + + finalBatch, err := a.State.GetBatchByNumber(ctx, proof.BatchNumberFinal, nil) + if err != nil { + log.Errorf("Failed to retrieve batch with number [%d]: %v", proof.BatchNumberFinal, err) + a.endProofVerification() + continue + } + + inputs := ethmanTypes.FinalProofInputs{ + FinalProof: msg.finalProof, + NewLocalExitRoot: finalBatch.LocalExitRoot.Bytes(), + NewStateRoot: finalBatch.StateRoot.Bytes(), + } + + log.Infof("Final proof inputs: NewLocalExitRoot [%#x], NewStateRoot [%#x]", inputs.NewLocalExitRoot, inputs.NewStateRoot) + + // add batch verification to be monitored + sender := common.HexToAddress(a.cfg.SenderAddress) + to, data, err := a.Ethman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs) + if err != nil { + log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + continue + } + monitoredTxID := buildMonitoredTxID(proof.BatchNumber, proof.BatchNumberFinal) + err = a.EthTxManager.Add(ctx, ethTxManagerOwner, monitoredTxID, sender, to, nil, data, nil) + if err != nil { + log := log.WithFields("tx", monitoredTxID) + log.Errorf("Error to add batch verification tx to eth tx manager: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + continue + } + + // process monitored batch verifications before starting a next cycle + a.EthTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) { + a.handleMonitoredTxResult(result) + }, nil) + + a.resetVerifyProofTime() + a.endProofVerification() + } + } +} + +func (a *Aggregator) handleFailureToAddVerifyBatchToBeMonitored(ctx context.Context, proof *state.Proof) { + log := log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal)) + proof.GeneratingSince = nil + err := a.State.UpdateGeneratedProof(ctx, proof, nil) + if err != nil { + log.Errorf("Failed updating proof state (false): %v", err) + } + a.endProofVerification() +} + +// buildFinalProof builds and return the final proof for an aggregated/batch proof. +func (a *Aggregator) buildFinalProof(ctx context.Context, prover proverInterface, proof *state.Proof) (*pb.FinalProof, error) { + log := log.WithFields( + "prover", prover.Name(), + "proverId", prover.ID(), + "proverAddr", prover.Addr(), + "recursiveProofId", *proof.ProofID, + "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal), + ) + log.Info("Generating final proof") + + finalProofID, err := prover.FinalProof(proof.Proof, a.cfg.SenderAddress) + if err != nil { + return nil, fmt.Errorf("failed to get final proof id: %w", err) + } + proof.ProofID = finalProofID + + log.Infof("Final proof ID for batches [%d-%d]: %s", proof.BatchNumber, proof.BatchNumberFinal, *proof.ProofID) + log = log.WithFields("finalProofId", finalProofID) + + finalProof, err := prover.WaitFinalProof(ctx, *proof.ProofID) + if err != nil { + return nil, fmt.Errorf("failed to get final proof from prover: %w", err) + } + + log.Info("Final proof generated") + + // mock prover sanity check + if string(finalProof.Public.NewStateRoot) == mockedStateRoot && string(finalProof.Public.NewLocalExitRoot) == mockedLocalExitRoot { + // This local exit root and state root come from the mock + // prover, use the one captured by the executor instead + finalBatch, err := a.State.GetBatchByNumber(ctx, proof.BatchNumberFinal, nil) + if err != nil { + return nil, fmt.Errorf("failed to retrieve batch with number [%d]", proof.BatchNumberFinal) + } + log.Warnf("NewLocalExitRoot and NewStateRoot look like a mock values, using values from executor instead: LER: %v, SR: %v", + finalBatch.LocalExitRoot.TerminalString(), finalBatch.StateRoot.TerminalString()) + finalProof.Public.NewStateRoot = finalBatch.StateRoot.Bytes() + finalProof.Public.NewLocalExitRoot = finalBatch.LocalExitRoot.Bytes() + } + + return finalProof, nil } -func (a *Aggregator) tryToSendVerifiedBatch(ctx context.Context, ticker *time.Ticker) { - log.Debug("checking if network is synced") - for !a.isSynced(ctx) { - log.Infof("waiting for synchronizer to sync...") - waitTick(ctx, ticker) +// tryBuildFinalProof checks if the provided proof is eligible to be used to +// build the final proof. If no proof is provided it looks for a previously +// generated proof. If the proof is eligible, then the final proof generation +// is triggered. +func (a *Aggregator) tryBuildFinalProof(ctx context.Context, prover proverInterface, proof *state.Proof) (bool, error) { + proverName := prover.Name() + proverID := prover.ID() + + log := log.WithFields( + "prover", proverName, + "proverId", proverID, + "proverAddr", prover.Addr(), + ) + log.Debug("tryBuildFinalProof start") + + var err error + if !a.canVerifyProof() { + log.Debug("Time to verify proof not reached or proof verification in progress") + return false, nil + } + log.Debug("Send final proof time reached") + + for !a.isSynced(ctx, nil) { + log.Info("Waiting for synchronizer to sync...") + time.Sleep(a.cfg.RetryTime.Duration) continue } - log.Debug("checking if there is any consolidated batch to be verified") + + var lastVerifiedBatchNum uint64 lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) - if err != nil && err != state.ErrNotFound { - log.Warnf("failed to get last consolidated batch, err: %v", err) - waitTick(ctx, ticker) - return - } else if err == state.ErrNotFound { - log.Debug("no consolidated batch found") - waitTick(ctx, ticker) - return - } - - batchNumberToVerify := lastVerifiedBatch.BatchNumber + 1 - - proof, err := a.State.GetGeneratedProofByBatchNumber(ctx, batchNumberToVerify, nil) - if err != nil && err != state.ErrNotFound { - log.Warnf("failed to get last proof for batch %v, err: %v", batchNumberToVerify, err) - waitTick(ctx, ticker) - return - } - - if proof != nil { - log.Infof("sending verified proof to the ethereum smart contract, batchNumber %d", batchNumberToVerify) - a.EthTxManager.VerifyBatch(batchNumberToVerify, proof) - log.Infof("proof for the batch was sent, batchNumber: %v", batchNumberToVerify) - /* - err := a.State.DeleteGeneratedProof(ctx, batchNumberToVerify, nil) + if err != nil && !errors.Is(err, state.ErrNotFound) { + return false, fmt.Errorf("failed to get last verified batch, %w", err) + } + if lastVerifiedBatch != nil { + lastVerifiedBatchNum = lastVerifiedBatch.BatchNumber + } + + if proof == nil { + // we don't have a proof generating at the moment, check if we + // have a proof ready to verify + + proof, err = a.getAndLockProofReadyToVerify(ctx, prover, lastVerifiedBatchNum) + if errors.Is(err, state.ErrNotFound) { + // nothing to verify, swallow the error + log.Debug("No proof ready to verify") + return false, nil + } + if err != nil { + return false, err + } + + defer func() { if err != nil { - log.Warnf("failed to delete generated proof for batchNumber %v, err: %v", batchNumberToVerify, err) - return + // Set the generating state to false for the proof ("unlock" it) + proof.GeneratingSince = nil + err2 := a.State.UpdateGeneratedProof(a.ctx, proof, nil) + if err2 != nil { + log.Errorf("Failed to unlock proof: %v", err2) + } } - */ + }() } else { - log.Debugf("no generated proof for batchNumber %v has been found", batchNumberToVerify) - waitTick(ctx, ticker) - return + // we do have a proof generating at the moment, check if it is + // eligible to be verified + eligible, err := a.validateEligibleFinalProof(ctx, proof, lastVerifiedBatchNum) + if err != nil { + return false, fmt.Errorf("failed to validate eligible final proof, %w", err) + } + if !eligible { + return false, nil + } + } + + log = log.WithFields( + "proofId", *proof.ProofID, + "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal), + ) + + // at this point we have an eligible proof, build the final one using it + finalProof, err := a.buildFinalProof(ctx, prover, proof) + if err != nil { + err = fmt.Errorf("failed to build final proof, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + msg := finalProofMsg{ + proverName: proverName, + proverID: proverID, + recursiveProof: proof, + finalProof: finalProof, } + + select { + case <-a.ctx.Done(): + return false, a.ctx.Err() + case a.finalProof <- msg: + } + + log.Debug("tryBuildFinalProof end") + return true, nil } -func (a *Aggregator) tryVerifyBatch(ctx context.Context, ticker *time.Ticker) { - log.Info("checking if network is synced") +func (a *Aggregator) validateEligibleFinalProof(ctx context.Context, proof *state.Proof, lastVerifiedBatchNum uint64) (bool, error) { + batchNumberToVerify := lastVerifiedBatchNum + 1 - for !a.isSynced(ctx) { - log.Infof("waiting for synchronizer to sync...") - waitTick(ctx, ticker) - continue + if proof.BatchNumber != batchNumberToVerify { + if proof.BatchNumber < batchNumberToVerify && proof.BatchNumberFinal >= batchNumberToVerify { + // We have a proof that contains some batches below the last batch verified, anyway can be eligible as final proof + log.Warnf("Proof %d-%d contains some batches lower than last batch verified %d. Check anyway if it is eligible", proof.BatchNumber, proof.BatchNumberFinal, lastVerifiedBatchNum) + } else if proof.BatchNumberFinal < batchNumberToVerify { + // We have a proof that contains batches below that the last batch verified, we need to delete this proof + log.Warnf("Proof %d-%d lower than next batch to verify %d. Deleting it", proof.BatchNumber, proof.BatchNumberFinal, batchNumberToVerify) + err := a.State.DeleteGeneratedProofs(ctx, proof.BatchNumber, proof.BatchNumberFinal, nil) + if err != nil { + return false, fmt.Errorf("failed to delete discarded proof, err: %w", err) + } + return false, nil + } else { + log.Debugf("Proof batch number %d is not the following to last verfied batch number %d", proof.BatchNumber, lastVerifiedBatchNum) + return false, nil + } + } + + bComplete, err := a.State.CheckProofContainsCompleteSequences(ctx, proof, nil) + if err != nil { + return false, fmt.Errorf("failed to check if proof contains complete sequences, %w", err) } - log.Info("network is synced, getting batch to verify") - batchToVerify, err := a.getBatchToVerify(ctx) - if err != nil || batchToVerify == nil { - waitTick(ctx, ticker) - return + if !bComplete { + log.Infof("Recursive proof %d-%d not eligible to be verified: not containing complete sequences", proof.BatchNumber, proof.BatchNumberFinal) + return false, nil } - log.Infof("checking profitability to aggregate batch, batchNumber: %d", batchToVerify.BatchNumber) - // pass matic collateral as zero here, bcs in smart contract fee for aggregator is not defined yet - isProfitable, err := a.ProfitabilityChecker.IsProfitable(ctx, big.NewInt(0)) + return true, nil +} + +func (a *Aggregator) getAndLockProofReadyToVerify(ctx context.Context, prover proverInterface, lastVerifiedBatchNum uint64) (*state.Proof, error) { + a.StateDBMutex.Lock() + defer a.StateDBMutex.Unlock() + + // Get proof ready to be verified + proofToVerify, err := a.State.GetProofReadyToVerify(ctx, lastVerifiedBatchNum, nil) if err != nil { - log.Warnf("failed to check aggregator profitability, err: %v", err) - waitTick(ctx, ticker) - return + return nil, err } - if !isProfitable { - log.Infof("Batch %d is not profitable, matic collateral %d", batchToVerify.BatchNumber, big.NewInt(0)) - waitTick(ctx, ticker) - return + now := time.Now().Round(time.Microsecond) + proofToVerify.GeneratingSince = &now + + err = a.State.UpdateGeneratedProof(ctx, proofToVerify, nil) + if err != nil { + return nil, err } - log.Infof("sending zki + batch to the prover, batchNumber: %d", batchToVerify.BatchNumber) - inputProver, err := a.buildInputProver(ctx, batchToVerify) + return proofToVerify, nil +} + +func (a *Aggregator) unlockProofsToAggregate(ctx context.Context, proof1 *state.Proof, proof2 *state.Proof) error { + // Release proofs from generating state in a single transaction + dbTx, err := a.State.BeginStateTransaction(ctx) if err != nil { - log.Warnf("failed to build input prover, err: %v", err) - waitTick(ctx, ticker) - return + log.Warnf("Failed to begin transaction to release proof aggregation state, err: %v", err) + return err } - log.Infof("sending a batch to the prover, OLDSTATEROOT: %s, NEWSTATEROOT: %s, BATCHNUM: %d", - inputProver.PublicInputs.OldStateRoot, inputProver.PublicInputs.NewStateRoot, inputProver.PublicInputs.BatchNum) + proof1.GeneratingSince = nil + err = a.State.UpdateGeneratedProof(ctx, proof1, dbTx) + if err == nil { + proof2.GeneratingSince = nil + err = a.State.UpdateGeneratedProof(ctx, proof2, dbTx) + } - var prover proverClientInterface - var idleProverFound bool - // Look for a free prover - for _, prover = range a.ProverClients { - if prover.IsIdle(ctx) { - log.Infof("Prover %s is going to be used for batchNumber: %d", prover.GetURI(), batchToVerify.BatchNumber) - idleProverFound = true - break + if err != nil { + if err := dbTx.Rollback(ctx); err != nil { + err := fmt.Errorf("failed to rollback proof aggregation state: %w", err) + log.Error(FirstToUpper(err.Error())) + return err } + return fmt.Errorf("failed to release proof aggregation state: %w", err) } - if !idleProverFound { - log.Warn("all provers are busy") - waitTick(ctx, ticker) - return + err = dbTx.Commit(ctx) + if err != nil { + return fmt.Errorf("failed to release proof aggregation state %w", err) } - // Avoid other thread to process the same batch - err = a.State.AddGeneratedProof(ctx, batchToVerify.BatchNumber, nil, nil) + return nil +} + +func (a *Aggregator) getAndLockProofsToAggregate(ctx context.Context, prover proverInterface) (*state.Proof, *state.Proof, error) { + log := log.WithFields( + "prover", prover.Name(), + "proverId", prover.ID(), + "proverAddr", prover.Addr(), + ) + + a.StateDBMutex.Lock() + defer a.StateDBMutex.Unlock() + + proof1, proof2, err := a.State.GetProofsToAggregate(ctx, nil) if err != nil { - log.Warnf("failed to store proof generation mark, err: %v", err) - waitTick(ctx, ticker) - return + return nil, nil, err + } + + // Set proofs in generating state in a single transaction + dbTx, err := a.State.BeginStateTransaction(ctx) + if err != nil { + log.Errorf("Failed to begin transaction to set proof aggregation state, err: %v", err) + return nil, nil, err + } + + now := time.Now().Round(time.Microsecond) + proof1.GeneratingSince = &now + err = a.State.UpdateGeneratedProof(ctx, proof1, dbTx) + if err == nil { + proof2.GeneratingSince = &now + err = a.State.UpdateGeneratedProof(ctx, proof2, dbTx) } - genProofID, err := prover.GetGenProofID(ctx, inputProver) if err != nil { - log.Warnf("failed to get gen proof id, err: %v", err) - err2 := a.State.DeleteGeneratedProof(ctx, batchToVerify.BatchNumber, nil) - if err2 != nil { - log.Errorf("failed to delete proof generation mark after error, err: %v", err2) + if err := dbTx.Rollback(ctx); err != nil { + err := fmt.Errorf("failed to rollback proof aggregation state %w", err) + log.Error(FirstToUpper(err.Error())) + return nil, nil, err } - waitTick(ctx, ticker) - return + return nil, nil, fmt.Errorf("failed to set proof aggregation state %w", err) + } + + err = dbTx.Commit(ctx) + if err != nil { + return nil, nil, fmt.Errorf("failed to set proof aggregation state %w", err) + } + + return proof1, proof2, nil +} + +func (a *Aggregator) tryAggregateProofs(ctx context.Context, prover proverInterface) (bool, error) { + proverName := prover.Name() + proverID := prover.ID() + + log := log.WithFields( + "prover", proverName, + "proverId", proverID, + "proverAddr", prover.Addr(), + ) + log.Debug("tryAggregateProofs start") + + proof1, proof2, err0 := a.getAndLockProofsToAggregate(ctx, prover) + if errors.Is(err0, state.ErrNotFound) { + // nothing to aggregate, swallow the error + log.Debug("Nothing to aggregate") + return false, nil + } + if err0 != nil { + return false, err0 } - log.Infof("Proof ID for batchNumber %d: %v", batchToVerify.BatchNumber, genProofID) + var ( + aggrProofID *string + err error + ) - resGetProof, err := prover.GetResGetProof(ctx, genProofID, batchToVerify.BatchNumber) + defer func() { + if err != nil { + err2 := a.unlockProofsToAggregate(a.ctx, proof1, proof2) + if err2 != nil { + log.Errorf("Failed to release aggregated proofs, err: %v", err2) + } + } + log.Debug("tryAggregateProofs end") + }() + + log.Infof("Aggregating proofs: %d-%d and %d-%d", proof1.BatchNumber, proof1.BatchNumberFinal, proof2.BatchNumber, proof2.BatchNumberFinal) + + batches := fmt.Sprintf("%d-%d", proof1.BatchNumber, proof2.BatchNumberFinal) + log = log.WithFields("batches", batches) + + inputProver := map[string]interface{}{ + "recursive_proof_1": proof1.Proof, + "recursive_proof_2": proof2.Proof, + } + b, err := json.Marshal(inputProver) if err != nil { - log.Warnf("failed to get proof from prover, err: %v", err) - err2 := a.State.DeleteGeneratedProof(ctx, batchToVerify.BatchNumber, nil) - if err2 != nil { - log.Errorf("failed to delete proof generation mark after error, err: %v", err2) + err = fmt.Errorf("failed to serialize input prover, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + proof := &state.Proof{ + BatchNumber: proof1.BatchNumber, + BatchNumberFinal: proof2.BatchNumberFinal, + Prover: &proverName, + ProverID: &proverID, + InputProver: string(b), + } + + aggrProofID, err = prover.AggregatedProof(proof1.Proof, proof2.Proof) + if err != nil { + err = fmt.Errorf("failed to get aggregated proof id, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + proof.ProofID = aggrProofID + + log.Infof("Proof ID for aggregated proof: %v", *proof.ProofID) + log = log.WithFields("proofId", *proof.ProofID) + + recursiveProof, err := prover.WaitRecursiveProof(ctx, *proof.ProofID) + if err != nil { + err = fmt.Errorf("failed to get aggregated proof from prover, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + log.Info("Aggregated proof generated") + + proof.Proof = recursiveProof + + // update the state by removing the 2 aggregated proofs and storing the + // newly generated recursive proof + dbTx, err := a.State.BeginStateTransaction(ctx) + if err != nil { + err = fmt.Errorf("failed to begin transaction to update proof aggregation state, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + err = a.State.DeleteGeneratedProofs(ctx, proof1.BatchNumber, proof2.BatchNumberFinal, dbTx) + if err != nil { + if err := dbTx.Rollback(ctx); err != nil { + err := fmt.Errorf("failed to rollback proof aggregation state, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - waitTick(ctx, ticker) - return + err = fmt.Errorf("failed to delete previously aggregated proofs, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - a.compareInputHashes(inputProver, resGetProof) - // Handle local exit root in the case of the mock prover - if resGetProof.Public.PublicInputs.NewLocalExitRoot == "0x17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e" { - // This local exit root comes from the mock, use the one captured by the executor instead - log.Warnf( - "NewLocalExitRoot looks like a mock value, using value from executor instead: %v", - inputProver.PublicInputs.NewLocalExitRoot, - ) - resGetProof.Public.PublicInputs.NewLocalExitRoot = inputProver.PublicInputs.NewLocalExitRoot + now := time.Now().Round(time.Microsecond) + proof.GeneratingSince = &now + + err = a.State.AddGeneratedProof(ctx, proof, dbTx) + if err != nil { + if err := dbTx.Rollback(ctx); err != nil { + err := fmt.Errorf("failed to rollback proof aggregation state, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + err = fmt.Errorf("failed to store the recursive proof, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - // Store proof - err = a.State.UpdateGeneratedProof(ctx, batchToVerify.BatchNumber, resGetProof, nil) + err = dbTx.Commit(ctx) if err != nil { - log.Warnf("failed to store generated proof, err: %v", err) - err2 := a.State.DeleteGeneratedProof(ctx, batchToVerify.BatchNumber, nil) - if err2 != nil { - log.Errorf("failed to delete proof generation mark after error, err: %v", err2) + err = fmt.Errorf("failed to store the recursive proof, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + // NOTE(pg): the defer func is useless from now on, use a different variable + // name for errors (or shadow err in inner scopes) to not trigger it. + + // state is up to date, check if we can send the final proof using the + // one just crafted. + finalProofBuilt, finalProofErr := a.tryBuildFinalProof(ctx, prover, proof) + if finalProofErr != nil { + // just log the error and continue to handle the aggregated proof + log.Errorf("Failed trying to check if recursive proof can be verified: %v", finalProofErr) + } + + // NOTE(pg): prover is done, use a.ctx from now on + + if !finalProofBuilt { + proof.GeneratingSince = nil + + // final proof has not been generated, update the recursive proof + err := a.State.UpdateGeneratedProof(a.ctx, proof, nil) + if err != nil { + err = fmt.Errorf("failed to store batch proof result, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - waitTick(ctx, ticker) - return } + + return true, nil } -func (a *Aggregator) isSynced(ctx context.Context) bool { +func (a *Aggregator) getAndLockBatchToProve(ctx context.Context, prover proverInterface) (*state.Batch, *state.Proof, error) { + proverID := prover.ID() + proverName := prover.Name() + + log := log.WithFields( + "prover", proverName, + "proverId", proverID, + "proverAddr", prover.Addr(), + ) + + a.StateDBMutex.Lock() + defer a.StateDBMutex.Unlock() + lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) - if err != nil && err != state.ErrNotFound { - log.Warnf("failed to get last consolidated batch, err: %v", err) - return false + if err != nil { + return nil, nil, err } - if lastVerifiedBatch == nil { - return false + + // Get virtual batch pending to generate proof + batchToVerify, err := a.State.GetVirtualBatchToProve(ctx, lastVerifiedBatch.BatchNumber, nil) + if err != nil { + return nil, nil, err } - lastVerifiedEthBatchNum, err := a.Ethman.GetLatestVerifiedBatchNum() + + log.Infof("Found virtual batch %d pending to generate proof", batchToVerify.BatchNumber) + log = log.WithFields("batch", batchToVerify.BatchNumber) + + log.Info("Checking profitability to aggregate batch") + + // pass matic collateral as zero here, bcs in smart contract fee for aggregator is not defined yet + isProfitable, err := a.ProfitabilityChecker.IsProfitable(ctx, big.NewInt(0)) if err != nil { - log.Warnf("failed to get last eth batch, err: %v", err) - return false + log.Errorf("Failed to check aggregator profitability, err: %v", err) + return nil, nil, err } - if lastVerifiedBatch.BatchNumber < lastVerifiedEthBatchNum { - log.Infof("waiting for the state to be synced, lastVerifiedBatchNum: %d, lastVerifiedEthBatchNum: %d", - lastVerifiedBatch.BatchNumber, lastVerifiedEthBatchNum) - return false + + if !isProfitable { + log.Infof("Batch is not profitable, matic collateral %d", big.NewInt(0)) + return nil, nil, err } - return true -} -func (a *Aggregator) getBatchToVerify(ctx context.Context) (*state.Batch, error) { - lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) + now := time.Now().Round(time.Microsecond) + proof := &state.Proof{ + BatchNumber: batchToVerify.BatchNumber, + BatchNumberFinal: batchToVerify.BatchNumber, + Prover: &proverName, + ProverID: &proverID, + GeneratingSince: &now, + } + + // Avoid other prover to process the same batch + err = a.State.AddGeneratedProof(ctx, proof, nil) if err != nil { - return nil, err + log.Errorf("Failed to add batch proof, err: %v", err) + return nil, nil, err } - batchNumberToVerify := lastVerifiedBatch.BatchNumber + 1 + return batchToVerify, proof, nil +} - // Check if a prover is already working on this batch - _, err = a.State.GetGeneratedProofByBatchNumber(ctx, batchNumberToVerify, nil) - if err != nil && !errors.Is(err, state.ErrNotFound) { - return nil, err +func (a *Aggregator) tryGenerateBatchProof(ctx context.Context, prover proverInterface) (bool, error) { + log := log.WithFields( + "prover", prover.Name(), + "proverId", prover.ID(), + "proverAddr", prover.Addr(), + ) + log.Debug("tryGenerateBatchProof start") + + batchToProve, proof, err0 := a.getAndLockBatchToProve(ctx, prover) + if errors.Is(err0, state.ErrNotFound) { + // nothing to proof, swallow the error + log.Debug("Nothing to generate proof") + return false, nil } + if err0 != nil { + return false, err0 + } + + log = log.WithFields("batch", batchToProve.BatchNumber) - for !errors.Is(err, state.ErrNotFound) { - batchNumberToVerify++ - _, err = a.State.GetGeneratedProofByBatchNumber(ctx, batchNumberToVerify, nil) - if err != nil && !errors.Is(err, state.ErrNotFound) { - return nil, err + var ( + genProofID *string + err error + ) + + defer func() { + if err != nil { + err2 := a.State.DeleteGeneratedProofs(a.ctx, proof.BatchNumber, proof.BatchNumberFinal, nil) + if err2 != nil { + log.Errorf("Failed to delete proof in progress, err: %v", err2) + } } + log.Debug("tryGenerateBatchProof end") + }() + + log.Info("Generating proof from batch") + + log.Infof("Sending zki + batch to the prover, batchNumber [%d]", batchToProve.BatchNumber) + inputProver, err := a.buildInputProver(ctx, batchToProve) + if err != nil { + err = fmt.Errorf("failed to build input prover, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - batchToVerify, err := a.State.GetVirtualBatchByNumber(ctx, batchNumberToVerify, nil) + b, err := json.Marshal(inputProver) if err != nil { - if errors.Is(err, state.ErrNotFound) { - log.Infof("there are no batches to consolidate") - return nil, err + err = fmt.Errorf("failed to serialize input prover, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + proof.InputProver = string(b) + + log.Infof("Sending a batch to the prover. OldStateRoot [%#x], OldBatchNum [%d]", + inputProver.PublicInputs.OldStateRoot, inputProver.PublicInputs.OldBatchNum) + + genProofID, err = prover.BatchProof(inputProver) + if err != nil { + err = fmt.Errorf("failed to get batch proof id, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + proof.ProofID = genProofID + + log.Infof("Proof ID %v", *proof.ProofID) + log = log.WithFields("proofId", *proof.ProofID) + + resGetProof, err := prover.WaitRecursiveProof(ctx, *proof.ProofID) + if err != nil { + err = fmt.Errorf("failed to get proof from prover, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err + } + + log.Info("Batch proof generated") + + proof.Proof = resGetProof + + // NOTE(pg): the defer func is useless from now on, use a different variable + // name for errors (or shadow err in inner scopes) to not trigger it. + + finalProofBuilt, finalProofErr := a.tryBuildFinalProof(ctx, prover, proof) + if finalProofErr != nil { + // just log the error and continue to handle the generated proof + log.Errorf("Error trying to build final proof: %v", finalProofErr) + } + + // NOTE(pg): prover is done, use a.ctx from now on + + if !finalProofBuilt { + proof.GeneratingSince = nil + + // final proof has not been generated, update the batch proof + err := a.State.UpdateGeneratedProof(a.ctx, proof, nil) + if err != nil { + err = fmt.Errorf("failed to store batch proof result, %w", err) + log.Error(FirstToUpper(err.Error())) + return false, err } - log.Warnf("failed to get batch to consolidate, err: %v", err) - return nil, err } - return batchToVerify, nil + + return true, nil +} + +// canVerifyProof returns true if we have reached the timeout to verify a proof +// and no other prover is verifying a proof (verifyingProof = false). +func (a *Aggregator) canVerifyProof() bool { + a.TimeSendFinalProofMutex.RLock() + defer a.TimeSendFinalProofMutex.RUnlock() + return a.TimeSendFinalProof.Before(time.Now()) && !a.verifyingProof +} + +// startProofVerification sets to true the verifyingProof variable to indicate that there is a proof verification in progress +func (a *Aggregator) startProofVerification() { + a.TimeSendFinalProofMutex.Lock() + defer a.TimeSendFinalProofMutex.Unlock() + a.verifyingProof = true +} + +// endProofVerification set verifyingProof to false to indicate that there is not proof verification in progress +func (a *Aggregator) endProofVerification() { + a.TimeSendFinalProofMutex.Lock() + defer a.TimeSendFinalProofMutex.Unlock() + a.verifyingProof = false +} + +// resetVerifyProofTime updates the timeout to verify a proof. +func (a *Aggregator) resetVerifyProofTime() { + a.TimeSendFinalProofMutex.Lock() + defer a.TimeSendFinalProofMutex.Unlock() + a.TimeSendFinalProof = time.Now().Add(a.cfg.VerifyProofInterval.Duration) +} + +// isSynced checks if the state is synchronized with L1. If a batch number is +// provided, it makes sure that the state is synced with that batch. +func (a *Aggregator) isSynced(ctx context.Context, batchNum *uint64) bool { + // get latest verified batch as seen by the synchronizer + lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) + if err == state.ErrNotFound { + return false + } + if err != nil { + log.Warnf("Failed to get last consolidated batch: %v", err) + return false + } + + if lastVerifiedBatch == nil { + return false + } + + if batchNum != nil && lastVerifiedBatch.BatchNumber < *batchNum { + log.Infof("Waiting for the state to be synced, lastVerifiedBatchNum: %d, waiting for batch: %d", lastVerifiedBatch.BatchNumber, batchNum) + return false + } + + // latest verified batch in L1 + lastVerifiedEthBatchNum, err := a.Ethman.GetLatestVerifiedBatchNum() + if err != nil { + log.Warnf("Failed to get last eth batch, err: %v", err) + return false + } + + // check if L2 is synced with L1 + if lastVerifiedBatch.BatchNumber < lastVerifiedEthBatchNum { + log.Infof("Waiting for the state to be synced, lastVerifiedBatchNum: %d, lastVerifiedEthBatchNum: %d, waiting for batch", + lastVerifiedBatch.BatchNumber, lastVerifiedEthBatchNum) + return false + } + + return true } func (a *Aggregator) buildInputProver(ctx context.Context, batchToVerify *state.Batch) (*pb.InputProver, error) { @@ -321,29 +978,19 @@ func (a *Aggregator) buildInputProver(ctx context.Context, batchToVerify *state. return nil, fmt.Errorf("failed to get previous batch, err: %v", err) } - blockTimestampByte := make([]byte, 8) //nolint:gomnd - binary.BigEndian.PutUint64(blockTimestampByte, uint64(batchToVerify.Timestamp.Unix())) - batchHashData := common.BytesToHash(keccak256.Hash( - batchToVerify.BatchL2Data, - batchToVerify.GlobalExitRoot[:], - blockTimestampByte, - batchToVerify.Coinbase[:], - )) inputProver := &pb.InputProver{ PublicInputs: &pb.PublicInputs{ - OldStateRoot: previousBatch.StateRoot.String(), - OldLocalExitRoot: previousBatch.LocalExitRoot.String(), - NewStateRoot: batchToVerify.StateRoot.String(), - NewLocalExitRoot: batchToVerify.LocalExitRoot.String(), - SequencerAddr: batchToVerify.Coinbase.String(), - BatchHashData: batchHashData.String(), - BatchNum: uint32(batchToVerify.BatchNumber), - EthTimestamp: uint64(batchToVerify.Timestamp.Unix()), - AggregatorAddr: a.Ethman.GetPublicAddress().String(), - ChainId: a.cfg.ChainID, + OldStateRoot: previousBatch.StateRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + OldBatchNum: previousBatch.BatchNumber, + ChainId: a.cfg.ChainID, + ForkId: a.cfg.ForkId, + BatchL2Data: batchToVerify.BatchL2Data, + GlobalExitRoot: batchToVerify.GlobalExitRoot.Bytes(), + EthTimestamp: uint64(batchToVerify.Timestamp.Unix()), + SequencerAddr: batchToVerify.Coinbase.String(), + AggregatorAddr: a.cfg.SenderAddress, }, - GlobalExitRoot: batchToVerify.GlobalExitRoot.String(), - BatchL2Data: hex.EncodeToString(batchToVerify.BatchL2Data), Db: map[string]string{}, ContractsBytecode: map[string]string{}, } @@ -351,51 +998,100 @@ func (a *Aggregator) buildInputProver(ctx context.Context, batchToVerify *state. return inputProver, nil } -func (a *Aggregator) compareInputHashes(ip *pb.InputProver, resGetProof *pb.GetProofResponse) { - // Calc inputHash - batchNumberByte := make([]byte, 4) //nolint:gomnd - binary.BigEndian.PutUint32(batchNumberByte, ip.PublicInputs.BatchNum) - blockTimestampByte := make([]byte, 8) //nolint:gomnd - binary.BigEndian.PutUint64(blockTimestampByte, ip.PublicInputs.EthTimestamp) - hash := keccak256.Hash( - []byte(ip.PublicInputs.OldStateRoot)[:], - []byte(ip.PublicInputs.OldLocalExitRoot)[:], - []byte(ip.PublicInputs.NewStateRoot)[:], - []byte(ip.PublicInputs.NewLocalExitRoot)[:], - []byte(ip.PublicInputs.SequencerAddr)[:], - []byte(ip.PublicInputs.BatchHashData)[:], - batchNumberByte[:], - blockTimestampByte[:], - ) - // Prime field. It is the prime number used as the order in our elliptic curve - const fr = "21888242871839275222246405745257275088548364400416034343698204186575808495617" - frB, _ := new(big.Int).SetString(fr, encoding.Base10) - inputHashMod := new(big.Int).Mod(new(big.Int).SetBytes(hash), frB) - internalInputHash := inputHashMod.Bytes() - - // InputHash must match - internalInputHashS := fmt.Sprintf("0x%064s", hex.EncodeToString(internalInputHash)) - publicInputsExtended := resGetProof.GetPublic() - if resGetProof.GetPublic().InputHash != internalInputHashS { - log.Error("inputHash received from the prover (", publicInputsExtended.InputHash, - ") doesn't match with the internal value: ", internalInputHashS) - log.Debug("internalBatchHashData: ", ip.PublicInputs.BatchHashData, " externalBatchHashData: ", publicInputsExtended.PublicInputs.BatchHashData) - log.Debug("inputProver.PublicInputs.OldStateRoot: ", ip.PublicInputs.OldStateRoot) - log.Debug("inputProver.PublicInputs.OldLocalExitRoot:", ip.PublicInputs.OldLocalExitRoot) - log.Debug("inputProver.PublicInputs.NewStateRoot: ", ip.PublicInputs.NewStateRoot) - log.Debug("inputProver.PublicInputs.NewLocalExitRoot: ", ip.PublicInputs.NewLocalExitRoot) - log.Debug("inputProver.PublicInputs.SequencerAddr: ", ip.PublicInputs.SequencerAddr) - log.Debug("inputProver.PublicInputs.BatchHashData: ", ip.PublicInputs.BatchHashData) - log.Debug("inputProver.PublicInputs.BatchNum: ", ip.PublicInputs.BatchNum) - log.Debug("inputProver.PublicInputs.EthTimestamp: ", ip.PublicInputs.EthTimestamp) +// healthChecker will provide an implementation of the HealthCheck interface. +type healthChecker struct{} + +// newHealthChecker returns a health checker according to standard package +// grpc.health.v1. +func newHealthChecker() *healthChecker { + return &healthChecker{} +} + +// HealthCheck interface implementation. + +// Check returns the current status of the server for unary gRPC health requests, +// for now if the server is up and able to respond we will always return SERVING. +func (hc *healthChecker) Check(ctx context.Context, req *grpchealth.HealthCheckRequest) (*grpchealth.HealthCheckResponse, error) { + log.Info("Serving the Check request for health check") + return &grpchealth.HealthCheckResponse{ + Status: grpchealth.HealthCheckResponse_SERVING, + }, nil +} + +// Watch returns the current status of the server for stream gRPC health requests, +// for now if the server is up and able to respond we will always return SERVING. +func (hc *healthChecker) Watch(req *grpchealth.HealthCheckRequest, server grpchealth.Health_WatchServer) error { + log.Info("Serving the Watch request for health check") + return server.Send(&grpchealth.HealthCheckResponse{ + Status: grpchealth.HealthCheckResponse_SERVING, + }) +} + +func (a *Aggregator) handleMonitoredTxResult(result ethtxmanager.MonitoredTxResult) { + resLog := log.WithFields("owner", ethTxManagerOwner, "txId", result.ID) + if result.Status == ethtxmanager.MonitoredTxStatusFailed { + resLog.Fatal("failed to send batch verification, TODO: review this fatal and define what to do in this case") + } + + // monitoredIDFormat: "proof-from-%v-to-%v" + idSlice := strings.Split(result.ID, "-") + proofBatchNumberStr := idSlice[2] + proofBatchNumber, err := strconv.ParseUint(proofBatchNumberStr, encoding.Base10, 0) + if err != nil { + resLog.Errorf("failed to read final proof batch number from monitored tx: %v", err) + } + + proofBatchNumberFinalStr := idSlice[4] + proofBatchNumberFinal, err := strconv.ParseUint(proofBatchNumberFinalStr, encoding.Base10, 0) + if err != nil { + resLog.Errorf("failed to read final proof batch number final from monitored tx: %v", err) + } + + log := log.WithFields("txId", result.ID, "batches", fmt.Sprintf("%d-%d", proofBatchNumber, proofBatchNumberFinal)) + log.Info("Final proof verified") + + // wait for the synchronizer to catch up the verified batches + log.Debug("A final proof has been sent, waiting for the network to be synced") + for !a.isSynced(a.ctx, &proofBatchNumberFinal) { + log.Info("Waiting for synchronizer to sync...") + time.Sleep(a.cfg.RetryTime.Duration) + } + + // network is synced with the final proof, we can safely delete all recursive + // proofs up to the last synced batch + err = a.State.CleanupGeneratedProofs(a.ctx, proofBatchNumberFinal, nil) + if err != nil { + log.Errorf("Failed to store proof aggregation result: %v", err) } } -func waitTick(ctx context.Context, ticker *time.Ticker) { - select { - case <-ticker.C: - // nothing - case <-ctx.Done(): - return +func buildMonitoredTxID(batchNumber, batchNumberFinal uint64) string { + return fmt.Sprintf(monitoredIDFormat, batchNumber, batchNumberFinal) +} + +func (a *Aggregator) cleanupLockedProofs() { + for { + select { + case <-a.ctx.Done(): + return + case <-time.After(a.TimeCleanupLockedProofs.Duration): + n, err := a.State.CleanupLockedProofs(a.ctx, a.cfg.GeneratingProofCleanupThreshold, nil) + if err != nil { + log.Errorf("Failed to cleanup locked proofs: %v", err) + } + if n == 1 { + log.Warn("Found a stale proof and removed form cache") + } else if n > 1 { + log.Warnf("Found %d stale proofs and removed from cache", n) + } + } } } + +// FirstToUpper returns the string passed as argument with the first letter in +// uppercase. +func FirstToUpper(s string) string { + runes := []rune(s) + runes[0] = unicode.ToUpper(runes[0]) + return string(runes) +} diff --git a/aggregator/aggregator_internal_test.go b/aggregator/aggregator_internal_test.go deleted file mode 100644 index 31a16cc90a..0000000000 --- a/aggregator/aggregator_internal_test.go +++ /dev/null @@ -1,292 +0,0 @@ -package aggregator - -import ( - "context" - "encoding/binary" - "errors" - "math/big" - "testing" - "time" - - aggrMocks "github.com/0xPolygonHermez/zkevm-node/aggregator/mocks" - cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/iden3/go-iden3-crypto/keccak256" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" -) - -func TestIsSynced(t *testing.T) { - st := new(aggrMocks.StateMock) - etherman := new(aggrMocks.Etherman) - a := Aggregator{State: st, Ethman: etherman} - ctx := context.Background() - verifiedBatch := &state.VerifiedBatch{BatchNumber: 1} - st.On("GetLastVerifiedBatch", ctx, nil).Return(verifiedBatch, nil) - etherman.On("GetLatestVerifiedBatchNum").Return(uint64(1), nil) - isSynced := a.isSynced(ctx) - require.True(t, isSynced) -} - -func TestIsSyncedNotSynced(t *testing.T) { - st := new(aggrMocks.StateMock) - etherman := new(aggrMocks.Etherman) - a := Aggregator{State: st, Ethman: etherman} - ctx := context.Background() - verifiedBatch := &state.VerifiedBatch{BatchNumber: 1} - st.On("GetLastVerifiedBatch", ctx, nil).Return(verifiedBatch, nil) - etherman.On("GetLatestVerifiedBatchNum").Return(uint64(2), nil) - isSynced := a.isSynced(ctx) - require.False(t, isSynced) -} - -func TestGetBatchToVerify(t *testing.T) { - st := new(aggrMocks.StateMock) - batchToVerify := &state.Batch{BatchNumber: 1} - a := Aggregator{State: st} - ctx := context.Background() - - verifiedBatch := &state.VerifiedBatch{BatchNumber: 1} - - st.On("GetLastVerifiedBatch", ctx, nil).Return(verifiedBatch, nil) - st.On("GetVirtualBatchByNumber", ctx, verifiedBatch.BatchNumber+1, nil).Return(batchToVerify, nil) - st.On("GetGeneratedProofByBatchNumber", ctx, verifiedBatch.BatchNumber+1, nil).Return(nil, state.ErrNotFound) - - res, err := a.getBatchToVerify(ctx) - require.NoError(t, err) - require.Equal(t, batchToVerify, res) -} - -func TestBuildInputProver(t *testing.T) { - st := new(aggrMocks.StateMock) - ethTxManager := new(aggrMocks.EthTxManager) - etherman := new(aggrMocks.Etherman) - proverClient := new(aggrMocks.ProverClientMock) - a := Aggregator{ - State: st, - EthTxManager: ethTxManager, - Ethman: etherman, - ProverClients: []proverClientInterface{proverClient}, - } - var ( - oldStateRoot = common.HexToHash("0xbdde84a5932a2f0a1a4c6c51f3b64ea265d4f1461749298cfdd09b31122ce0d6") - newStateRoot = common.HexToHash("0x613aabebf4fddf2ad0f034a8c73aa2f9c5a6fac3a07543023e0a6ee6f36e5795") - oldLocalExitRoot = common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1") - newLocalExitRoot = common.HexToHash("0x40a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0") - seqAddress = common.HexToAddress("0x123") - batchL2Data = []byte("data") - previousBatch = &state.Batch{ - BatchNumber: 1, - StateRoot: oldStateRoot, - LocalExitRoot: oldLocalExitRoot, - } - ) - - ctx := context.Background() - - verifiedBatch := &state.VerifiedBatch{BatchNumber: 1} - - st.On("GetLastVerifiedBatch", ctx, nil).Return(verifiedBatch, nil) - etherman.On("GetLatestVerifiedBatchNum").Return(verifiedBatch.BatchNumber, nil) - - lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) - require.NoError(t, err) - - st.On("GetBatchByNumber", mock.Anything, lastVerifiedBatch.BatchNumber, nil).Return(previousBatch, nil) - - tx := *types.NewTransaction(1, common.HexToAddress("1"), big.NewInt(1), 0, big.NewInt(1), []byte("bbb")) - batchToVerify := &state.Batch{ - BatchNumber: 2, - Coinbase: seqAddress, - BatchL2Data: batchL2Data, - StateRoot: newStateRoot, - LocalExitRoot: newLocalExitRoot, - Timestamp: time.Now(), - Transactions: []types.Transaction{tx}, - GlobalExitRoot: common.HexToHash("0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb"), - } - - expectedInputProver := &pb.InputProver{ - PublicInputs: &pb.PublicInputs{ - OldStateRoot: oldStateRoot.String(), - OldLocalExitRoot: oldLocalExitRoot.String(), - NewStateRoot: newStateRoot.String(), - NewLocalExitRoot: newLocalExitRoot.String(), - SequencerAddr: seqAddress.String(), - BatchHashData: hex.EncodeToString(batchL2Data), - BatchNum: uint32(batchToVerify.BatchNumber), - EthTimestamp: uint64(batchToVerify.Timestamp.Unix()), - }, - GlobalExitRoot: batchToVerify.GlobalExitRoot.String(), - BatchL2Data: hex.EncodeToString(batchL2Data), - } - - etherman.On("GetPublicAddress").Return(common.HexToAddress("0x123")) - ip, err := a.buildInputProver(ctx, batchToVerify) - require.NoError(t, err) - require.NotNil(t, ip) - require.Equal(t, expectedInputProver.PublicInputs.BatchNum, ip.PublicInputs.BatchNum) - require.Equal(t, expectedInputProver.PublicInputs.OldStateRoot, ip.PublicInputs.OldStateRoot) - require.Equal(t, expectedInputProver.PublicInputs.OldLocalExitRoot, ip.PublicInputs.OldLocalExitRoot) - require.Equal(t, expectedInputProver.PublicInputs.NewStateRoot, ip.PublicInputs.NewStateRoot) - require.Equal(t, expectedInputProver.PublicInputs.NewLocalExitRoot, ip.PublicInputs.NewLocalExitRoot) - require.Equal(t, expectedInputProver.PublicInputs.SequencerAddr, ip.PublicInputs.SequencerAddr) - require.Equal(t, expectedInputProver.PublicInputs.EthTimestamp, ip.PublicInputs.EthTimestamp) - require.Equal(t, expectedInputProver.GlobalExitRoot, ip.GlobalExitRoot) - require.Equal(t, expectedInputProver.BatchL2Data, ip.BatchL2Data) -} - -func TestBuildInputProverError(t *testing.T) { - st := new(aggrMocks.StateMock) - ethTxManager := new(aggrMocks.EthTxManager) - etherman := new(aggrMocks.Etherman) - proverClient := new(aggrMocks.ProverClientMock) - a := Aggregator{ - State: st, - EthTxManager: ethTxManager, - Ethman: etherman, - ProverClients: []proverClientInterface{proverClient}, - } - var ( - newLocalExitRoot = common.HexToHash("0xbdde84a5932a2f0a1a4c6c51f3b64ea265d4f1461749298cfdd09b31122ce0d6") - seqAddress = common.HexToAddress("0x123") - batchL2Data = []byte("data") - ) - ctx := context.Background() - - verifiedBatch := &state.VerifiedBatch{BatchNumber: 1} - - st.On("GetLastVerifiedBatch", ctx, nil).Return(verifiedBatch, nil) - etherman.On("GetLatestVerifiedBatchNum").Return(verifiedBatch.BatchNumber, nil) - - lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(ctx, nil) - require.NoError(t, err) - - st.On("GetBatchByNumber", mock.Anything, lastVerifiedBatch.BatchNumber, nil).Return(nil, errors.New("error")) - - tx := *types.NewTransaction(1, common.HexToAddress("1"), big.NewInt(1), 0, big.NewInt(1), []byte("bbb")) - batchToVerify := &state.Batch{ - BatchNumber: 2, - Coinbase: seqAddress, - BatchL2Data: batchL2Data, - LocalExitRoot: newLocalExitRoot, - Timestamp: time.Now(), - Transactions: []types.Transaction{tx}, - GlobalExitRoot: common.HexToHash("0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb"), - } - - ip, err := a.buildInputProver(ctx, batchToVerify) - require.Error(t, err) - require.Nil(t, ip) -} - -func TestAggregatorFlow(t *testing.T) { - st := new(aggrMocks.StateMock) - ethTxManager := new(aggrMocks.EthTxManager) - etherman := new(aggrMocks.Etherman) - proverClient := new(aggrMocks.ProverClientMock) - a := Aggregator{ - cfg: Config{ - IntervalToConsolidateState: cfgTypes.NewDuration(1 * time.Second), - ChainID: 1000, - }, - State: st, - EthTxManager: ethTxManager, - Ethman: etherman, - ProverClients: []proverClientInterface{proverClient}, - ProfitabilityChecker: NewTxProfitabilityCheckerAcceptAll(st, 1*time.Second), - } - var ( - oldStateRoot = common.HexToHash("0xbdde84a5932a2f0a1a4c6c51f3b64ea265d4f1461749298cfdd09b31122ce0d6") - newStateRoot = common.HexToHash("0x613aabebf4fddf2ad0f034a8c73aa2f9c5a6fac3a07543023e0a6ee6f36e5795") - oldLocalExitRoot = common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1") - newLocalExitRoot = common.HexToHash("0x40a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0") - seqAddress = common.HexToAddress("0x123") - aggrAddress = common.HexToAddress("0x123") - verifiedBatch = &state.VerifiedBatch{BatchNumber: 1} - tx = *types.NewTransaction(1, common.HexToAddress("1"), big.NewInt(1), 0, big.NewInt(1), []byte("bbb")) - previousBatch = &state.Batch{ - BatchNumber: 1, - StateRoot: oldStateRoot, - LocalExitRoot: oldLocalExitRoot, - } - batchToVerify = &state.Batch{ - BatchNumber: 2, - Coinbase: seqAddress, - StateRoot: newStateRoot, - LocalExitRoot: newLocalExitRoot, - Timestamp: time.Now(), - Transactions: []types.Transaction{tx}, - GlobalExitRoot: common.HexToHash("0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb"), - } - expectedInputProver = &pb.InputProver{ - PublicInputs: &pb.PublicInputs{ - OldStateRoot: oldStateRoot.String(), - OldLocalExitRoot: oldLocalExitRoot.String(), - NewStateRoot: newStateRoot.String(), - NewLocalExitRoot: newLocalExitRoot.String(), - SequencerAddr: seqAddress.String(), - BatchNum: uint32(batchToVerify.BatchNumber), - EthTimestamp: uint64(batchToVerify.Timestamp.Unix()), - AggregatorAddr: aggrAddress.String(), - ChainId: a.cfg.ChainID, - }, - GlobalExitRoot: batchToVerify.GlobalExitRoot.String(), - Db: map[string]string{}, - ContractsBytecode: map[string]string{}, - } - getProofResponse = &pb.GetProofResponse{ - Id: "1", - Proof: &pb.Proof{ - ProofA: []string{"1"}, - ProofB: []*pb.ProofB{}, - ProofC: []string{"1"}, - }, - Public: &pb.PublicInputsExtended{ - PublicInputs: expectedInputProver.PublicInputs, - InputHash: "0x2df6320fec1fa7dafa408f9c5f2b31603b2148cb02063935d2e4d105121c1967", - }, - Result: 1, - ResultString: "1", - } - ) - blockTimestampByte := make([]byte, 8) //nolint:gomnd - binary.BigEndian.PutUint64(blockTimestampByte, uint64(batchToVerify.Timestamp.Unix())) - batchHashData := common.BytesToHash(keccak256.Hash( - batchToVerify.BatchL2Data, - batchToVerify.GlobalExitRoot[:], - blockTimestampByte, - batchToVerify.Coinbase[:], - )) - expectedInputProver.PublicInputs.BatchHashData = batchHashData.String() - // isSynced - proverClient.On("IsIdle", mock.Anything).Return(true) - proverClient.On("GetURI", mock.Anything).Return("mockProver:MockPort") - st.On("GetLastVerifiedBatch", mock.Anything, nil).Return(verifiedBatch, nil) - st.On("GetGeneratedProofByBatchNumber", mock.Anything, verifiedBatch.BatchNumber+1, nil).Return(nil, state.ErrNotFound) - st.On("AddGeneratedProof", mock.Anything, mock.Anything, mock.Anything, nil).Return(nil) - st.On("UpdateGeneratedProof", mock.Anything, mock.Anything, mock.Anything, nil).Return(nil) - etherman.On("GetLatestVerifiedBatchNum").Return(uint64(1), nil) - etherman.On("GetPublicAddress").Return(aggrAddress) - - lastVerifiedBatch, err := a.State.GetLastVerifiedBatch(context.Background(), nil) - require.NoError(t, err) - // get batch to verify - st.On("GetVirtualBatchByNumber", mock.Anything, lastVerifiedBatch.BatchNumber+1, nil).Return(batchToVerify, nil) - // build input prover - st.On("GetBatchByNumber", mock.Anything, lastVerifiedBatch.BatchNumber, nil).Return(previousBatch, nil) - // gen proof id - proverClient.On("GetGenProofID", mock.Anything, expectedInputProver).Return("1", nil) - // get proof - proverClient.On("GetResGetProof", mock.Anything, "1", batchToVerify.BatchNumber).Return(getProofResponse, nil) - // send proof to the eth - ethTxManager.On("VerifyBatch", batchToVerify.BatchNumber, getProofResponse).Return(nil) - ticker := time.NewTicker(a.cfg.IntervalToConsolidateState.Duration) - defer ticker.Stop() - ctx := context.Background() - a.tryVerifyBatch(ctx, ticker) -} diff --git a/aggregator/aggregator_test.go b/aggregator/aggregator_test.go new file mode 100644 index 0000000000..f75d7237f3 --- /dev/null +++ b/aggregator/aggregator_test.go @@ -0,0 +1,1387 @@ +package aggregator + +import ( + "context" + "encoding/json" + "errors" + "math/big" + "sync" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/aggregator/mocks" + "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" + configTypes "github.com/0xPolygonHermez/zkevm-node/config/types" + ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +type mox struct { + stateMock *mocks.StateMock + ethTxManager *mocks.EthTxManager + etherman *mocks.Etherman + proverMock *mocks.ProverMock +} + +func TestSendFinalProof(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + errBanana := errors.New("banana") + batchNum := uint64(23) + batchNumFinal := uint64(42) + from := common.BytesToAddress([]byte("from")) + to := common.BytesToAddress([]byte("to")) + var value *big.Int + data := []byte("data") + finalBatch := state.Batch{ + LocalExitRoot: common.BytesToHash([]byte("localExitRoot")), + StateRoot: common.BytesToHash([]byte("stateRoot")), + } + proofID := "proofId" + proverName := "proverName" + proverID := "proverID" + recursiveProof := &state.Proof{ + Prover: &proverName, + ProverID: &proverID, + ProofID: &proofID, + BatchNumber: batchNum, + BatchNumberFinal: batchNumFinal, + } + finalProof := &pb.FinalProof{} + cfg := Config{SenderAddress: from.Hex()} + + testCases := []struct { + name string + setup func(mox, *Aggregator) + asserts func(*Aggregator) + }{ + { + name: "GetBatchByNumber error", + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetBatchByNumber", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + // test is done, stop the sendFinalProof method + a.exit() + assert.True(a.verifyingProof) + }).Return(nil, errBanana).Once() + }, + asserts: func(a *Aggregator) { + assert.False(a.verifyingProof) + }, + }, + { + name: "BuildTrustedVerifyBatchesTxData error", + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetBatchByNumber", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&finalBatch, nil).Once() + expectedInputs := ethmanTypes.FinalProofInputs{ + FinalProof: finalProof, + NewLocalExitRoot: finalBatch.LocalExitRoot.Bytes(), + NewStateRoot: finalBatch.StateRoot.Bytes(), + } + m.etherman.On("BuildTrustedVerifyBatchesTxData", batchNum-1, batchNumFinal, &expectedInputs).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(nil, nil, errBanana).Once() + m.stateMock.On("UpdateGeneratedProof", mock.Anything, recursiveProof, nil).Run(func(args mock.Arguments) { + // test is done, stop the sendFinalProof method + a.exit() + }).Return(nil).Once() + }, + asserts: func(a *Aggregator) { + assert.False(a.verifyingProof) + }, + }, + { + name: "UpdateGeneratedProof error after BuildTrustedVerifyBatchesTxData error", + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetBatchByNumber", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&finalBatch, nil).Once() + expectedInputs := ethmanTypes.FinalProofInputs{ + FinalProof: finalProof, + NewLocalExitRoot: finalBatch.LocalExitRoot.Bytes(), + NewStateRoot: finalBatch.StateRoot.Bytes(), + } + m.etherman.On("BuildTrustedVerifyBatchesTxData", batchNum-1, batchNumFinal, &expectedInputs).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(nil, nil, errBanana).Once() + m.stateMock.On("UpdateGeneratedProof", mock.Anything, recursiveProof, nil).Run(func(args mock.Arguments) { + // test is done, stop the sendFinalProof method + a.exit() + }).Return(errBanana).Once() + }, + asserts: func(a *Aggregator) { + assert.False(a.verifyingProof) + }, + }, + { + name: "EthTxManager Add error", + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetBatchByNumber", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&finalBatch, nil).Once() + expectedInputs := ethmanTypes.FinalProofInputs{ + FinalProof: finalProof, + NewLocalExitRoot: finalBatch.LocalExitRoot.Bytes(), + NewStateRoot: finalBatch.StateRoot.Bytes(), + } + m.etherman.On("BuildTrustedVerifyBatchesTxData", batchNum-1, batchNumFinal, &expectedInputs).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&to, data, nil).Once() + monitoredTxID := buildMonitoredTxID(batchNum, batchNumFinal) + m.ethTxManager.On("Add", mock.Anything, ethTxManagerOwner, monitoredTxID, from, &to, value, data, nil).Return(errBanana).Once() + m.stateMock.On("UpdateGeneratedProof", mock.Anything, recursiveProof, nil).Run(func(args mock.Arguments) { + // test is done, stop the sendFinalProof method + a.exit() + }).Return(nil).Once() + }, + asserts: func(a *Aggregator) { + assert.False(a.verifyingProof) + }, + }, + { + name: "nominal case", + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetBatchByNumber", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&finalBatch, nil).Once() + expectedInputs := ethmanTypes.FinalProofInputs{ + FinalProof: finalProof, + NewLocalExitRoot: finalBatch.LocalExitRoot.Bytes(), + NewStateRoot: finalBatch.StateRoot.Bytes(), + } + m.etherman.On("BuildTrustedVerifyBatchesTxData", batchNum-1, batchNumFinal, &expectedInputs).Run(func(args mock.Arguments) { + assert.True(a.verifyingProof) + }).Return(&to, data, nil).Once() + monitoredTxID := buildMonitoredTxID(batchNum, batchNumFinal) + m.ethTxManager.On("Add", mock.Anything, ethTxManagerOwner, monitoredTxID, from, &to, value, data, nil).Return(nil).Once() + ethTxManResult := ethtxmanager.MonitoredTxResult{ + ID: monitoredTxID, + Status: ethtxmanager.MonitoredTxStatusConfirmed, + Txs: map[common.Hash]ethtxmanager.TxResult{}, + } + m.ethTxManager.On("ProcessPendingMonitoredTxs", mock.Anything, ethTxManagerOwner, mock.Anything, nil).Run(func(args mock.Arguments) { + args[2].(ethtxmanager.ResultHandler)(ethTxManResult, nil) // this calls a.handleMonitoredTxResult + }).Once() + verifiedBatch := state.VerifiedBatch{ + BatchNumber: batchNumFinal, + } + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&verifiedBatch, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(batchNumFinal, nil).Once() + m.stateMock.On("CleanupGeneratedProofs", mock.Anything, batchNumFinal, nil).Run(func(args mock.Arguments) { + // test is done, stop the sendFinalProof method + a.exit() + }).Return(nil).Once() + }, + asserts: func(a *Aggregator) { + assert.False(a.verifyingProof) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stateMock := mocks.NewStateMock(t) + ethTxManager := mocks.NewEthTxManager(t) + etherman := mocks.NewEtherman(t) + a, err := New(cfg, stateMock, ethTxManager, etherman) + require.NoError(err) + a.ctx, a.exit = context.WithCancel(context.Background()) + m := mox{ + stateMock: stateMock, + ethTxManager: ethTxManager, + etherman: etherman, + } + if tc.setup != nil { + tc.setup(m, &a) + } + // send a final proof over the channel + go func() { + finalMsg := finalProofMsg{ + proverID: proverID, + recursiveProof: recursiveProof, + finalProof: finalProof, + } + a.finalProof <- finalMsg + }() + + a.sendFinalProof() + + if tc.asserts != nil { + tc.asserts(&a) + } + }) + } +} + +func TestTryAggregateProofs(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + errBanana := errors.New("banana") + cfg := Config{ + VerifyProofInterval: configTypes.NewDuration(10000000), + } + proofID := "proofId" + proverName := "proverName" + proverID := "proverID" + recursiveProof := "recursiveProof" + proverCtx := context.WithValue(context.Background(), "owner", "prover") //nolint:staticcheck + matchProverCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "prover" } + matchAggregatorCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "aggregator" } + batchNum := uint64(23) + batchNumFinal := uint64(42) + proof1 := state.Proof{ + Proof: "proof1", + BatchNumber: batchNum, + } + proof2 := state.Proof{ + Proof: "proof2", + BatchNumberFinal: batchNumFinal, + } + testCases := []struct { + name string + setup func(mox, *Aggregator) + asserts func(bool, *Aggregator, error) + }{ + { + name: "getAndLockProofsToAggregate returns generic error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, nil, errBanana).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "getAndLockProofsToAggregate returns ErrNotFound", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, nil, state.ErrNotFound).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "getAndLockProofsToAggregate error updating proofs", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + dbTx.On("Rollback", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(errBanana). + Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "AggregatedProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + lockProofsTxBegin := m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Once() + lockProofsTxCommit := dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + proof1GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + proof2GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(nil, errBanana).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchAggregatorCtxFn)).Return(dbTx, nil).Once().NotBefore(lockProofsTxBegin) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof1GeneratingTrueCall) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof2GeneratingTrueCall) + dbTx.On("Commit", mock.MatchedBy(matchAggregatorCtxFn)).Return(nil).Once().NotBefore(lockProofsTxCommit) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "WaitRecursiveProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + lockProofsTxBegin := m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Once() + lockProofsTxCommit := dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + proof1GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + proof2GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return("", errBanana).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchAggregatorCtxFn)).Return(dbTx, nil).Once().NotBefore(lockProofsTxBegin) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof1GeneratingTrueCall) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof2GeneratingTrueCall) + dbTx.On("Commit", mock.MatchedBy(matchAggregatorCtxFn)).Return(nil).Once().NotBefore(lockProofsTxCommit) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "unlockProofsToAggregate error after WaitRecursiveProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return(proverID) + dbTx := &mocks.DbTxMock{} + lockProofsTxBegin := m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Once() + dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + proof1GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return("", errBanana).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchAggregatorCtxFn)).Return(dbTx, nil).Once().NotBefore(lockProofsTxBegin) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(errBanana). + Once(). + NotBefore(proof1GeneratingTrueCall) + dbTx.On("Rollback", mock.MatchedBy(matchAggregatorCtxFn)).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "rollback after DeleteGeneratedProofs error in db transaction", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + lockProofsTxBegin := m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Twice() + lockProofsTxCommit := dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + proof1GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + proof2GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchProverCtxFn), proof1.BatchNumber, proof2.BatchNumberFinal, dbTx).Return(errBanana).Once() + dbTx.On("Rollback", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchAggregatorCtxFn)).Return(dbTx, nil).Once().NotBefore(lockProofsTxBegin) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof1GeneratingTrueCall) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof2GeneratingTrueCall) + dbTx.On("Commit", mock.MatchedBy(matchAggregatorCtxFn)).Return(nil).Once().NotBefore(lockProofsTxCommit) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "rollback after AddGeneratedProof error in db transaction", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + lockProofsTxBegin := m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Twice() + lockProofsTxCommit := dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + proof1GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + proof2GeneratingTrueCall := m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchProverCtxFn), proof1.BatchNumber, proof2.BatchNumberFinal, dbTx).Return(nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, dbTx).Return(errBanana).Once() + dbTx.On("Rollback", mock.MatchedBy(matchProverCtxFn)).Return(nil).Once() + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchAggregatorCtxFn)).Return(dbTx, nil).Once().NotBefore(lockProofsTxBegin) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof1GeneratingTrueCall) + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.Nil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once(). + NotBefore(proof2GeneratingTrueCall) + dbTx.On("Commit", mock.MatchedBy(matchAggregatorCtxFn)).Return(nil).Once().NotBefore(lockProofsTxCommit) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "not time to send final ok", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Times(3) + m.proverMock.On("ID").Return(proverID).Times(3) + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Twice() + dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Twice() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchProverCtxFn), proof1.BatchNumber, proof2.BatchNumberFinal, dbTx).Return(nil).Once() + expectedInputProver := map[string]interface{}{ + "recursive_proof_1": proof1.Proof, + "recursive_proof_2": proof2.Proof, + } + b, err := json.Marshal(expectedInputProver) + require.NoError(err) + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, dbTx).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(proof1.BatchNumber, proof.BatchNumber) + assert.Equal(proof2.BatchNumberFinal, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(proof1.BatchNumber, proof.BatchNumber) + assert.Equal(proof2.BatchNumberFinal, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.Nil(proof.GeneratingSince) + }, + ).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + }, + { + name: "time to send final, state error ok", + setup: func(m mox, a *Aggregator) { + a.cfg.VerifyProofInterval = configTypes.NewDuration(1) + m.proverMock.On("Name").Return(proverName).Times(3) + m.proverMock.On("ID").Return(proverID).Times(3) + m.proverMock.On("Addr").Return("addr") + dbTx := &mocks.DbTxMock{} + m.stateMock.On("BeginStateTransaction", mock.MatchedBy(matchProverCtxFn)).Return(dbTx, nil).Twice() + dbTx.On("Commit", mock.MatchedBy(matchProverCtxFn)).Return(nil).Twice() + m.stateMock.On("GetProofsToAggregate", mock.MatchedBy(matchProverCtxFn), nil).Return(&proof1, &proof2, nil).Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof1, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proof2, dbTx). + Run(func(args mock.Arguments) { + assert.NotNil(args[1].(*state.Proof).GeneratingSince) + }). + Return(nil). + Once() + m.proverMock.On("AggregatedProof", proof1.Proof, proof2.Proof).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchProverCtxFn), proof1.BatchNumber, proof2.BatchNumberFinal, dbTx).Return(nil).Once() + expectedInputProver := map[string]interface{}{ + "recursive_proof_1": proof1.Proof, + "recursive_proof_2": proof2.Proof, + } + b, err := json.Marshal(expectedInputProver) + require.NoError(err) + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, dbTx).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(proof1.BatchNumber, proof.BatchNumber) + assert.Equal(proof2.BatchNumberFinal, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + isSyncedCall := m.stateMock. + On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil). + Return(&state.VerifiedBatch{BatchNumber: uint64(42)}, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(uint64(42), nil).Once() + // make tryBuildFinalProof fail ASAP + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, errBanana).Once().NotBefore(isSyncedCall) + m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(proof1.BatchNumber, proof.BatchNumber) + assert.Equal(proof2.BatchNumberFinal, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.Nil(proof.GeneratingSince) + }, + ).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stateMock := mocks.NewStateMock(t) + ethTxManager := mocks.NewEthTxManager(t) + etherman := mocks.NewEtherman(t) + proverMock := mocks.NewProverMock(t) + a, err := New(cfg, stateMock, ethTxManager, etherman) + require.NoError(err) + aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck + a.ctx, a.exit = context.WithCancel(aggregatorCtx) + m := mox{ + stateMock: stateMock, + ethTxManager: ethTxManager, + etherman: etherman, + proverMock: proverMock, + } + if tc.setup != nil { + tc.setup(m, &a) + } + a.resetVerifyProofTime() + + result, err := a.tryAggregateProofs(proverCtx, proverMock) + + if tc.asserts != nil { + tc.asserts(result, &a, err) + } + }) + } +} + +func TestTryGenerateBatchProof(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + from := common.BytesToAddress([]byte("from")) + cfg := Config{ + VerifyProofInterval: configTypes.NewDuration(10000000), + TxProfitabilityCheckerType: ProfitabilityAcceptAll, + SenderAddress: from.Hex(), + } + lastVerifiedBatchNum := uint64(22) + batchNum := uint64(23) + lastVerifiedBatch := state.VerifiedBatch{ + BatchNumber: lastVerifiedBatchNum, + } + latestBatch := state.Batch{ + BatchNumber: lastVerifiedBatchNum, + } + batchToProve := state.Batch{ + BatchNumber: batchNum, + } + proofID := "proofId" + proverName := "proverName" + proverID := "proverID" + recursiveProof := "recursiveProof" + errBanana := errors.New("banana") + proverCtx := context.WithValue(context.Background(), "owner", "prover") //nolint:staticcheck + matchProverCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "prover" } + matchAggregatorCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "aggregator" } + testCases := []struct { + name string + setup func(mox, *Aggregator) + asserts func(bool, *Aggregator, error) + }{ + { + name: "getAndLockBatchToProve returns generic error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, errBanana).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "getAndLockBatchToProve returns ErrNotFound", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, state.ErrNotFound).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "BatchProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("GetBatchByNumber", mock.Anything, lastVerifiedBatchNum, nil).Return(&latestBatch, nil).Twice() + expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) + require.NoError(err) + m.proverMock.On("BatchProof", expectedInputProver).Return(nil, errBanana).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchAggregatorCtxFn), batchToProve.BatchNumber, batchToProve.BatchNumber, nil).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "WaitRecursiveProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("GetBatchByNumber", mock.Anything, lastVerifiedBatchNum, nil).Return(&latestBatch, nil).Twice() + expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) + require.NoError(err) + m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return("", errBanana).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchAggregatorCtxFn), batchToProve.BatchNumber, batchToProve.BatchNumber, nil).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "DeleteGeneratedProofs error after WaitRecursiveProof prover error", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return(proverID) + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("GetBatchByNumber", mock.Anything, lastVerifiedBatchNum, nil).Return(&latestBatch, nil).Twice() + expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) + require.NoError(err) + m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return("", errBanana).Once() + m.stateMock.On("DeleteGeneratedProofs", mock.MatchedBy(matchAggregatorCtxFn), batchToProve.BatchNumber, batchToProve.BatchNumber, nil).Return(errBanana).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "not time to send final ok", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Times(3) + m.proverMock.On("ID").Return(proverID).Times(3) + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("GetBatchByNumber", mock.Anything, lastVerifiedBatchNum, nil).Return(&latestBatch, nil).Twice() + expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) + require.NoError(err) + m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + b, err := json.Marshal(expectedInputProver) + require.NoError(err) + m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.Nil(proof.GeneratingSince) + }, + ).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + }, + { + name: "time to send final, state error ok", + setup: func(m mox, a *Aggregator) { + a.cfg.VerifyProofInterval = configTypes.NewDuration(0) + m.proverMock.On("Name").Return(proverName).Times(3) + m.proverMock.On("ID").Return(proverID).Times(3) + m.proverMock.On("Addr").Return("addr") + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&lastVerifiedBatch, nil).Once() + m.stateMock.On("GetVirtualBatchToProve", mock.MatchedBy(matchProverCtxFn), lastVerifiedBatchNum, nil).Return(&batchToProve, nil).Once() + m.stateMock.On("AddGeneratedProof", mock.MatchedBy(matchProverCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.InDelta(time.Now().Unix(), proof.GeneratingSince.Unix(), float64(time.Second)) + }, + ).Return(nil).Once() + m.stateMock.On("GetBatchByNumber", mock.Anything, lastVerifiedBatchNum, nil).Return(&latestBatch, nil).Twice() + expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve) + require.NoError(err) + m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once() + m.proverMock.On("WaitRecursiveProof", mock.MatchedBy(matchProverCtxFn), proofID).Return(recursiveProof, nil).Once() + b, err := json.Marshal(expectedInputProver) + require.NoError(err) + isSyncedCall := m.stateMock. + On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil). + Return(&state.VerifiedBatch{BatchNumber: uint64(42)}, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(uint64(42), nil).Once() + // make tryBuildFinalProof fail ASAP + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(nil, errBanana).Once().NotBefore(isSyncedCall) + m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), mock.Anything, nil).Run( + func(args mock.Arguments) { + proof := args[1].(*state.Proof) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumber) + assert.Equal(batchToProve.BatchNumber, proof.BatchNumberFinal) + assert.Equal(&proverName, proof.Prover) + assert.Equal(&proverID, proof.ProverID) + assert.Equal(string(b), proof.InputProver) + assert.Equal(recursiveProof, proof.Proof) + assert.Nil(proof.GeneratingSince) + }, + ).Return(nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stateMock := mocks.NewStateMock(t) + ethTxManager := mocks.NewEthTxManager(t) + etherman := mocks.NewEtherman(t) + proverMock := mocks.NewProverMock(t) + a, err := New(cfg, stateMock, ethTxManager, etherman) + require.NoError(err) + aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck + a.ctx, a.exit = context.WithCancel(aggregatorCtx) + m := mox{ + stateMock: stateMock, + ethTxManager: ethTxManager, + etherman: etherman, + proverMock: proverMock, + } + if tc.setup != nil { + tc.setup(m, &a) + } + a.resetVerifyProofTime() + + result, err := a.tryGenerateBatchProof(proverCtx, proverMock) + + if tc.asserts != nil { + tc.asserts(result, &a, err) + } + }) + } +} + +func TestTryBuildFinalProof(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + errBanana := errors.New("banana") + from := common.BytesToAddress([]byte("from")) + cfg := Config{ + VerifyProofInterval: configTypes.NewDuration(10000000), + TxProfitabilityCheckerType: ProfitabilityAcceptAll, + SenderAddress: from.Hex(), + } + latestVerifiedBatchNum := uint64(22) + batchNum := uint64(23) + batchNumFinal := uint64(42) + proofID := "proofID" + proof := "proof" + proverName := "proverName" + proverID := "proverID" + finalProofID := "finalProofID" + finalProof := pb.FinalProof{ + Proof: "", + Public: &pb.PublicInputsExtended{ + NewStateRoot: []byte("newStateRoot"), + NewLocalExitRoot: []byte("newLocalExitRoot"), + }, + } + proofToVerify := state.Proof{ + ProofID: &proofID, + Proof: proof, + BatchNumber: batchNum, + BatchNumberFinal: batchNumFinal, + } + invalidProof := state.Proof{ + ProofID: &proofID, + Proof: proof, + BatchNumber: uint64(123), + BatchNumberFinal: uint64(456), + } + verifiedBatch := state.VerifiedBatch{ + BatchNumber: latestVerifiedBatchNum, + } + proverCtx := context.WithValue(context.Background(), "owner", "prover") //nolint:staticcheck + matchProverCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "prover" } + matchAggregatorCtxFn := func(ctx context.Context) bool { return ctx.Value("owner") == "aggregator" } + testCases := []struct { + name string + proof *state.Proof + setup func(mox, *Aggregator) + asserts func(bool, *Aggregator, error) + assertFinalMsg func(*finalProofMsg) + }{ + { + name: "can't verify proof (verifyingProof = true)", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return("addr").Once() + a.verifyingProof = true + }, + asserts: func(result bool, a *Aggregator, err error) { + a.verifyingProof = false // reset + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "can't verify proof (veryfy time not reached yet)", + setup: func(m mox, a *Aggregator) { + a.TimeSendFinalProof = time.Now().Add(10 * time.Second) + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return("addr").Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "nil proof, error requesting the proof triggers defer", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr").Twice() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("GetProofReadyToVerify", mock.MatchedBy(matchProverCtxFn), latestVerifiedBatchNum, nil).Return(&proofToVerify, nil).Once() + proofGeneratingTrueCall := m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(nil).Once() + m.proverMock.On("FinalProof", proofToVerify.Proof, from.String()).Return(nil, errBanana).Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proofToVerify, nil). + Return(nil). + Once(). + NotBefore(proofGeneratingTrueCall) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "nil proof, error building the proof triggers defer", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return("addr").Twice() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("GetProofReadyToVerify", mock.MatchedBy(matchProverCtxFn), latestVerifiedBatchNum, nil).Return(&proofToVerify, nil).Once() + proofGeneratingTrueCall := m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(nil).Once() + m.proverMock.On("FinalProof", proofToVerify.Proof, from.String()).Return(&finalProofID, nil).Once() + m.proverMock.On("WaitFinalProof", mock.MatchedBy(matchProverCtxFn), finalProofID).Return(nil, errBanana).Once() + m.stateMock. + On("UpdateGeneratedProof", mock.MatchedBy(matchAggregatorCtxFn), &proofToVerify, nil). + Return(nil). + Once(). + NotBefore(proofGeneratingTrueCall) + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "nil proof, generic error from GetProofReadyToVerify", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return(proverID).Once() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("GetProofReadyToVerify", mock.MatchedBy(matchProverCtxFn), latestVerifiedBatchNum, nil).Return(nil, errBanana).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "nil proof, ErrNotFound from GetProofReadyToVerify", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return(proverID).Once() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("GetProofReadyToVerify", mock.MatchedBy(matchProverCtxFn), latestVerifiedBatchNum, nil).Return(nil, state.ErrNotFound).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "nil proof gets a proof ready to verify", + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return(proverID).Twice() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("GetProofReadyToVerify", mock.MatchedBy(matchProverCtxFn), latestVerifiedBatchNum, nil).Return(&proofToVerify, nil).Once() + m.stateMock.On("UpdateGeneratedProof", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(nil).Once() + m.proverMock.On("FinalProof", proofToVerify.Proof, from.String()).Return(&finalProofID, nil).Once() + m.proverMock.On("WaitFinalProof", mock.MatchedBy(matchProverCtxFn), finalProofID).Return(&finalProof, nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + assertFinalMsg: func(msg *finalProofMsg) { + assert.Equal(finalProof.Proof, msg.finalProof.Proof) + assert.Equal(finalProof.Public.NewStateRoot, msg.finalProof.Public.NewStateRoot) + assert.Equal(finalProof.Public.NewLocalExitRoot, msg.finalProof.Public.NewLocalExitRoot) + }, + }, + { + name: "error checking if proof is a complete sequence", + proof: &proofToVerify, + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return(proverID).Once() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("CheckProofContainsCompleteSequences", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(false, errBanana).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.ErrorIs(err, errBanana) + }, + }, + { + name: "invalid proof (not consecutive to latest verified batch) rejected", + proof: &invalidProof, + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return(proverID).Once() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "invalid proof (not a complete sequence) rejected", + proof: &proofToVerify, + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Once() + m.proverMock.On("ID").Return(proverID).Once() + m.proverMock.On("Addr").Return(proverID).Once() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("CheckProofContainsCompleteSequences", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(false, nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.False(result) + assert.NoError(err) + }, + }, + { + name: "valid proof ok", + proof: &proofToVerify, + setup: func(m mox, a *Aggregator) { + m.proverMock.On("Name").Return(proverName).Twice() + m.proverMock.On("ID").Return(proverID).Twice() + m.proverMock.On("Addr").Return(proverID).Twice() + m.stateMock.On("GetLastVerifiedBatch", mock.MatchedBy(matchProverCtxFn), nil).Return(&verifiedBatch, nil).Twice() + m.etherman.On("GetLatestVerifiedBatchNum").Return(latestVerifiedBatchNum, nil).Once() + m.stateMock.On("CheckProofContainsCompleteSequences", mock.MatchedBy(matchProverCtxFn), &proofToVerify, nil).Return(true, nil).Once() + m.proverMock.On("FinalProof", proofToVerify.Proof, from.String()).Return(&finalProofID, nil).Once() + m.proverMock.On("WaitFinalProof", mock.MatchedBy(matchProverCtxFn), finalProofID).Return(&finalProof, nil).Once() + }, + asserts: func(result bool, a *Aggregator, err error) { + assert.True(result) + assert.NoError(err) + }, + assertFinalMsg: func(msg *finalProofMsg) { + assert.Equal(finalProof.Proof, msg.finalProof.Proof) + assert.Equal(finalProof.Public.NewStateRoot, msg.finalProof.Public.NewStateRoot) + assert.Equal(finalProof.Public.NewLocalExitRoot, msg.finalProof.Public.NewLocalExitRoot) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stateMock := mocks.NewStateMock(t) + ethTxManager := mocks.NewEthTxManager(t) + etherman := mocks.NewEtherman(t) + proverMock := mocks.NewProverMock(t) + a, err := New(cfg, stateMock, ethTxManager, etherman) + require.NoError(err) + aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck + a.ctx, a.exit = context.WithCancel(aggregatorCtx) + m := mox{ + stateMock: stateMock, + ethTxManager: ethTxManager, + etherman: etherman, + proverMock: proverMock, + } + if tc.setup != nil { + tc.setup(m, &a) + } + var wg sync.WaitGroup + if tc.assertFinalMsg != nil { + // wait for the final proof over the channel + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + msg := <-a.finalProof + tc.assertFinalMsg(&msg) + }() + } + + result, err := a.tryBuildFinalProof(proverCtx, proverMock, tc.proof) + + if tc.asserts != nil { + tc.asserts(result, &a, err) + } + if tc.assertFinalMsg != nil { + testutils.WaitUntil(t, &wg, time.Second) + } + }) + } +} + +func TestIsSynced(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + cfg := Config{} + var nilBatchNum *uint64 + batchNum := uint64(42) + errBanana := errors.New("banana") + testCases := []struct { + name string + setup func(mox, *Aggregator) + batchNum *uint64 + synced bool + }{ + { + name: "state ErrNotFound", + synced: false, + batchNum: &batchNum, + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(nil, state.ErrNotFound).Once() + }, + }, + { + name: "state error", + synced: false, + batchNum: &batchNum, + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(nil, errBanana).Once() + }, + }, + { + name: "state returns nil batch", + synced: false, + batchNum: &batchNum, + setup: func(m mox, a *Aggregator) { + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(nil, nil).Once() + }, + }, + { + name: "etherman error", + synced: false, + batchNum: nilBatchNum, + setup: func(m mox, a *Aggregator) { + latestVerifiedBatch := state.VerifiedBatch{BatchNumber: uint64(1)} + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&latestVerifiedBatch, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(uint64(0), errBanana).Once() + }, + }, + { + name: "not synced with provided batch number", + synced: false, + batchNum: &batchNum, + setup: func(m mox, a *Aggregator) { + latestVerifiedBatch := state.VerifiedBatch{BatchNumber: uint64(1)} + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&latestVerifiedBatch, nil).Once() + }, + }, + { + name: "not synced with nil batch number", + synced: false, + batchNum: nilBatchNum, + setup: func(m mox, a *Aggregator) { + latestVerifiedBatch := state.VerifiedBatch{BatchNumber: uint64(1)} + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&latestVerifiedBatch, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(batchNum, nil).Once() + }, + }, + { + name: "ok with nil batch number", + synced: true, + batchNum: nilBatchNum, + setup: func(m mox, a *Aggregator) { + latestVerifiedBatch := state.VerifiedBatch{BatchNumber: batchNum} + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&latestVerifiedBatch, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(batchNum, nil).Once() + }, + }, + { + name: "ok with batch number", + synced: true, + batchNum: &batchNum, + setup: func(m mox, a *Aggregator) { + latestVerifiedBatch := state.VerifiedBatch{BatchNumber: batchNum} + m.stateMock.On("GetLastVerifiedBatch", mock.Anything, nil).Return(&latestVerifiedBatch, nil).Once() + m.etherman.On("GetLatestVerifiedBatchNum").Return(batchNum, nil).Once() + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stateMock := mocks.NewStateMock(t) + ethTxManager := mocks.NewEthTxManager(t) + etherman := mocks.NewEtherman(t) + proverMock := mocks.NewProverMock(t) + a, err := New(cfg, stateMock, ethTxManager, etherman) + require.NoError(err) + aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck + a.ctx, a.exit = context.WithCancel(aggregatorCtx) + m := mox{ + stateMock: stateMock, + ethTxManager: ethTxManager, + etherman: etherman, + proverMock: proverMock, + } + if tc.setup != nil { + tc.setup(m, &a) + } + + synced := a.isSynced(a.ctx, tc.batchNum) + + assert.Equal(tc.synced, synced) + }) + } +} diff --git a/aggregator/config.go b/aggregator/config.go index 9be23031e8..63b1a1ffca 100644 --- a/aggregator/config.go +++ b/aggregator/config.go @@ -30,13 +30,20 @@ func (t *TokenAmountWithDecimals) UnmarshalText(data []byte) error { // Config represents the configuration of the aggregator type Config struct { - // IntervalToConsolidateState is the time the aggregator waits until - // trying to consolidate a new state - IntervalToConsolidateState types.Duration `mapstructure:"IntervalToConsolidateState"` + // Host for the grpc server + Host string `mapstructure:"Host"` + // Port for the grpc server + Port int `mapstructure:"Port"` - // IntervalFrequencyToGetProofGenerationState is the time the aggregator waits until - // trying to get proof generation status, in case prover client returns PENDING state - IntervalFrequencyToGetProofGenerationState types.Duration `mapstructure:"IntervalFrequencyToGetProofGenerationState"` + // RetryTime is the time the aggregator main loop sleeps if there are no proofs to aggregate + // or batches to generate proofs. It is also used in the isSynced loop + RetryTime types.Duration `mapstructure:"RetryTime"` + + // VerifyProofInterval is the interval of time to verify/send an proof in L1 + VerifyProofInterval types.Duration `mapstructure:"VerifyProofInterval"` + + // ProofStatePollingInterval is the interval time to polling the prover about the generation state of a proof + ProofStatePollingInterval types.Duration `mapstructure:"ProofStatePollingInterval"` // TxProfitabilityCheckerType type for checking is it profitable for aggregator to validate batch // possible values: base/acceptall @@ -52,6 +59,18 @@ type Config struct { // ChainID is the L2 ChainID provided by the Network Config ChainID uint64 - // Array of Prover URIs read from configuration file - ProverURIs []string + // ForkID is the L2 ForkID provided by the Network Config + ForkId uint64 `mapstructure:"ForkId"` + + // SenderAddress defines which private key the eth tx manager needs to use + // to sign the L1 txs + SenderAddress string `mapstructure:"SenderAddress"` + + // CleanupLockedProofsInterval is the interval of time to clean up locked proofs. + CleanupLockedProofsInterval types.Duration `mapstructure:"CleanupLockedProofsInterval"` + + // GeneratingProofCleanupThreshold represents the time interval after + // which a proof in generating state is considered to be stuck and + // allowed to be cleared. + GeneratingProofCleanupThreshold string `mapstructure:"GeneratingProofCleanupThreshold"` } diff --git a/aggregator/interfaces.go b/aggregator/interfaces.go index 258ec1a66b..f957e5178f 100644 --- a/aggregator/interfaces.go +++ b/aggregator/interfaces.go @@ -4,7 +4,9 @@ import ( "context" "math/big" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" + "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" + ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" "github.com/jackc/pgx/v4" @@ -12,16 +14,31 @@ import ( // Consumer interfaces required by the package. +type proverInterface interface { + Name() string + ID() string + Addr() string + IsIdle() (bool, error) + BatchProof(input *pb.InputProver) (*string, error) + AggregatedProof(inputProof1, inputProof2 string) (*string, error) + FinalProof(inputProof string, aggregatorAddr string) (*string, error) + WaitRecursiveProof(ctx context.Context, proofID string) (string, error) + WaitFinalProof(ctx context.Context, proofID string) (*pb.FinalProof, error) +} + // ethTxManager contains the methods required to send txs to // ethereum. type ethTxManager interface { - VerifyBatch(batchNum uint64, proof *pb.GetProofResponse) + Add(ctx context.Context, owner, id string, from common.Address, to *common.Address, value *big.Int, data []byte, dbTx pgx.Tx) error + Result(ctx context.Context, owner, id string, dbTx pgx.Tx) (ethtxmanager.MonitoredTxResult, error) + ResultsByStatus(ctx context.Context, owner string, statuses []ethtxmanager.MonitoredTxStatus, dbTx pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error) + ProcessPendingMonitoredTxs(ctx context.Context, owner string, failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) } // etherman contains the methods required to interact with ethereum type etherman interface { GetLatestVerifiedBatchNum() (uint64, error) - GetPublicAddress() common.Address + BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, inputs *ethmanTypes.FinalProofInputs) (to *common.Address, data []byte, err error) } // aggregatorTxProfitabilityChecker interface for different profitability @@ -30,22 +47,19 @@ type aggregatorTxProfitabilityChecker interface { IsProfitable(context.Context, *big.Int) (bool, error) } -// proverClient is a wrapper to the prover service -type proverClientInterface interface { - GetURI() string - IsIdle(ctx context.Context) bool - GetGenProofID(ctx context.Context, inputProver *pb.InputProver) (string, error) - GetResGetProof(ctx context.Context, genProofID string, batchNumber uint64) (*pb.GetProofResponse, error) -} - // stateInterface gathers the methods to interact with the state. type stateInterface interface { + BeginStateTransaction(ctx context.Context) (pgx.Tx, error) + CheckProofContainsCompleteSequences(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) (bool, error) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) - GetVirtualBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + GetProofReadyToVerify(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Proof, error) + GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + GetProofsToAggregate(ctx context.Context, dbTx pgx.Tx) (*state.Proof, *state.Proof, error) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) - AddGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error - UpdateGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error - GetGeneratedProofByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*pb.GetProofResponse, error) - DeleteGeneratedProof(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error + AddGeneratedProof(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) error + UpdateGeneratedProof(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) error + DeleteGeneratedProofs(ctx context.Context, batchNumber uint64, batchNumberFinal uint64, dbTx pgx.Tx) error DeleteUngeneratedProofs(ctx context.Context, dbTx pgx.Tx) error + CleanupGeneratedProofs(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error + CleanupLockedProofs(ctx context.Context, duration string, dbTx pgx.Tx) (int64, error) } diff --git a/aggregator/metrics/metrics.go b/aggregator/metrics/metrics.go new file mode 100644 index 0000000000..ea8bed4242 --- /dev/null +++ b/aggregator/metrics/metrics.go @@ -0,0 +1,51 @@ +package metrics + +import ( + "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + prefix = "aggregator_" + currentConnectedProversName = prefix + "current_connected_provers" + currentWorkingProversName = prefix + "current_working_provers" +) + +// Register the metrics for the sequencer package. +func Register() { + gauges := []prometheus.GaugeOpts{ + { + Name: currentConnectedProversName, + Help: "[AGGREGATOR] current connected provers", + }, + { + Name: currentWorkingProversName, + Help: "[AGGREGATOR] current working provers", + }, + } + + metrics.RegisterGauges(gauges...) +} + +// ConnectedProver increments the gauge for the current number of connected +// provers. +func ConnectedProver() { + metrics.GaugeInc(currentConnectedProversName) +} + +// DisconnectedProver decrements the gauge for the current number of connected +// provers. +func DisconnectedProver() { + metrics.GaugeDec(currentConnectedProversName) +} + +// WorkingProver increments the gauge for the current number of working +// provers. +func WorkingProver() { + metrics.GaugeInc(currentWorkingProversName) +} + +// IdlingProver decrements the gauge for the current number of working provers. +func IdlingProver() { + metrics.GaugeDec(currentWorkingProversName) +} diff --git a/jsonrpc/mock_dbtx_test.go b/aggregator/mocks/mock_dbtx.go similarity index 74% rename from jsonrpc/mock_dbtx_test.go rename to aggregator/mocks/mock_dbtx.go index 1715f99fac..8ad33d476e 100644 --- a/jsonrpc/mock_dbtx_test.go +++ b/aggregator/mocks/mock_dbtx.go @@ -1,6 +1,6 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. -package jsonrpc +package mocks import ( context "context" @@ -11,16 +11,20 @@ import ( pgx "github.com/jackc/pgx/v4" ) -// dbTxMock is an autogenerated mock type for the Tx type -type dbTxMock struct { +// DbTxMock is an autogenerated mock type for the Tx type +type DbTxMock struct { mock.Mock } // Begin provides a mock function with given fields: ctx -func (_m *dbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { +func (_m *DbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { ret := _m.Called(ctx) var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { r0 = rf(ctx) } else { @@ -29,7 +33,6 @@ func (_m *dbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -40,7 +43,7 @@ func (_m *dbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { } // BeginFunc provides a mock function with given fields: ctx, f -func (_m *dbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { +func (_m *DbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { ret := _m.Called(ctx, f) var r0 error @@ -54,7 +57,7 @@ func (_m *dbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { } // Commit provides a mock function with given fields: ctx -func (_m *dbTxMock) Commit(ctx context.Context) error { +func (_m *DbTxMock) Commit(ctx context.Context) error { ret := _m.Called(ctx) var r0 error @@ -68,7 +71,7 @@ func (_m *dbTxMock) Commit(ctx context.Context) error { } // Conn provides a mock function with given fields: -func (_m *dbTxMock) Conn() *pgx.Conn { +func (_m *DbTxMock) Conn() *pgx.Conn { ret := _m.Called() var r0 *pgx.Conn @@ -84,17 +87,20 @@ func (_m *dbTxMock) Conn() *pgx.Conn { } // CopyFrom provides a mock function with given fields: ctx, tableName, columnNames, rowSrc -func (_m *dbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { +func (_m *DbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { ret := _m.Called(ctx, tableName, columnNames, rowSrc) var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)); ok { + return rf(ctx, tableName, columnNames, rowSrc) + } if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) int64); ok { r0 = rf(ctx, tableName, columnNames, rowSrc) } else { r0 = ret.Get(0).(int64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) error); ok { r1 = rf(ctx, tableName, columnNames, rowSrc) } else { @@ -105,13 +111,17 @@ func (_m *dbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, colu } // Exec provides a mock function with given fields: ctx, sql, arguments -func (_m *dbTxMock) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) { +func (_m *DbTxMock) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) { var _ca []interface{} _ca = append(_ca, ctx, sql) _ca = append(_ca, arguments...) ret := _m.Called(_ca...) var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, arguments...) + } if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgconn.CommandTag); ok { r0 = rf(ctx, sql, arguments...) } else { @@ -120,7 +130,6 @@ func (_m *dbTxMock) Exec(ctx context.Context, sql string, arguments ...interface } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { r1 = rf(ctx, sql, arguments...) } else { @@ -131,7 +140,7 @@ func (_m *dbTxMock) Exec(ctx context.Context, sql string, arguments ...interface } // LargeObjects provides a mock function with given fields: -func (_m *dbTxMock) LargeObjects() pgx.LargeObjects { +func (_m *DbTxMock) LargeObjects() pgx.LargeObjects { ret := _m.Called() var r0 pgx.LargeObjects @@ -145,10 +154,14 @@ func (_m *dbTxMock) LargeObjects() pgx.LargeObjects { } // Prepare provides a mock function with given fields: ctx, name, sql -func (_m *dbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgconn.StatementDescription, error) { +func (_m *DbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgconn.StatementDescription, error) { ret := _m.Called(ctx, name, sql) var r0 *pgconn.StatementDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*pgconn.StatementDescription, error)); ok { + return rf(ctx, name, sql) + } if rf, ok := ret.Get(0).(func(context.Context, string, string) *pgconn.StatementDescription); ok { r0 = rf(ctx, name, sql) } else { @@ -157,7 +170,6 @@ func (_m *dbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgco } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { r1 = rf(ctx, name, sql) } else { @@ -168,13 +180,17 @@ func (_m *dbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgco } // Query provides a mock function with given fields: ctx, sql, args -func (_m *dbTxMock) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) { +func (_m *DbTxMock) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) { var _ca []interface{} _ca = append(_ca, ctx, sql) _ca = append(_ca, args...) ret := _m.Called(_ca...) var r0 pgx.Rows + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgx.Rows, error)); ok { + return rf(ctx, sql, args...) + } if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Rows); ok { r0 = rf(ctx, sql, args...) } else { @@ -183,7 +199,6 @@ func (_m *dbTxMock) Query(ctx context.Context, sql string, args ...interface{}) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { r1 = rf(ctx, sql, args...) } else { @@ -194,10 +209,14 @@ func (_m *dbTxMock) Query(ctx context.Context, sql string, args ...interface{}) } // QueryFunc provides a mock function with given fields: ctx, sql, args, scans, f -func (_m *dbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error) { +func (_m *DbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error) { ret := _m.Called(ctx, sql, args, scans, f) var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, args, scans, f) + } if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) pgconn.CommandTag); ok { r0 = rf(ctx, sql, args, scans, f) } else { @@ -206,7 +225,6 @@ func (_m *dbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{ } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) error); ok { r1 = rf(ctx, sql, args, scans, f) } else { @@ -217,7 +235,7 @@ func (_m *dbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{ } // QueryRow provides a mock function with given fields: ctx, sql, args -func (_m *dbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row { +func (_m *DbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row { var _ca []interface{} _ca = append(_ca, ctx, sql) _ca = append(_ca, args...) @@ -236,7 +254,7 @@ func (_m *dbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{ } // Rollback provides a mock function with given fields: ctx -func (_m *dbTxMock) Rollback(ctx context.Context) error { +func (_m *DbTxMock) Rollback(ctx context.Context) error { ret := _m.Called(ctx) var r0 error @@ -250,7 +268,7 @@ func (_m *dbTxMock) Rollback(ctx context.Context) error { } // SendBatch provides a mock function with given fields: ctx, b -func (_m *dbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { +func (_m *DbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { ret := _m.Called(ctx, b) var r0 pgx.BatchResults @@ -265,14 +283,14 @@ func (_m *dbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResult return r0 } -type mockConstructorTestingTnewDbTxMock interface { +type mockConstructorTestingTNewDbTxMock interface { mock.TestingT Cleanup(func()) } -// newDbTxMock creates a new instance of dbTxMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func newDbTxMock(t mockConstructorTestingTnewDbTxMock) *dbTxMock { - mock := &dbTxMock{} +// NewDbTxMock creates a new instance of DbTxMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewDbTxMock(t mockConstructorTestingTNewDbTxMock) *DbTxMock { + mock := &DbTxMock{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/aggregator/mocks/mock_etherman.go b/aggregator/mocks/mock_etherman.go index 1daff5f0d9..50831aac38 100644 --- a/aggregator/mocks/mock_etherman.go +++ b/aggregator/mocks/mock_etherman.go @@ -1,10 +1,12 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package mocks import ( common "github.com/ethereum/go-ethereum/common" mock "github.com/stretchr/testify/mock" + + types "github.com/0xPolygonHermez/zkevm-node/etherman/types" ) // Etherman is an autogenerated mock type for the etherman type @@ -12,18 +14,56 @@ type Etherman struct { mock.Mock } +// BuildTrustedVerifyBatchesTxData provides a mock function with given fields: lastVerifiedBatch, newVerifiedBatch, inputs +func (_m *Etherman) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch uint64, newVerifiedBatch uint64, inputs *types.FinalProofInputs) (*common.Address, []byte, error) { + ret := _m.Called(lastVerifiedBatch, newVerifiedBatch, inputs) + + var r0 *common.Address + var r1 []byte + var r2 error + if rf, ok := ret.Get(0).(func(uint64, uint64, *types.FinalProofInputs) (*common.Address, []byte, error)); ok { + return rf(lastVerifiedBatch, newVerifiedBatch, inputs) + } + if rf, ok := ret.Get(0).(func(uint64, uint64, *types.FinalProofInputs) *common.Address); ok { + r0 = rf(lastVerifiedBatch, newVerifiedBatch, inputs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*common.Address) + } + } + + if rf, ok := ret.Get(1).(func(uint64, uint64, *types.FinalProofInputs) []byte); ok { + r1 = rf(lastVerifiedBatch, newVerifiedBatch, inputs) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]byte) + } + } + + if rf, ok := ret.Get(2).(func(uint64, uint64, *types.FinalProofInputs) error); ok { + r2 = rf(lastVerifiedBatch, newVerifiedBatch, inputs) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // GetLatestVerifiedBatchNum provides a mock function with given fields: func (_m *Etherman) GetLatestVerifiedBatchNum() (uint64, error) { ret := _m.Called() var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func() (uint64, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() uint64); ok { r0 = rf() } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -33,22 +73,6 @@ func (_m *Etherman) GetLatestVerifiedBatchNum() (uint64, error) { return r0, r1 } -// GetPublicAddress provides a mock function with given fields: -func (_m *Etherman) GetPublicAddress() common.Address { - ret := _m.Called() - - var r0 common.Address - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - return r0 -} - type mockConstructorTestingTNewEtherman interface { mock.TestingT Cleanup(func()) diff --git a/aggregator/mocks/mock_ethtxmanager.go b/aggregator/mocks/mock_ethtxmanager.go index 9dfa32f862..8aeae6304a 100644 --- a/aggregator/mocks/mock_ethtxmanager.go +++ b/aggregator/mocks/mock_ethtxmanager.go @@ -1,10 +1,18 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package mocks import ( - pb "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + ethtxmanager "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" ) // EthTxManager is an autogenerated mock type for the ethTxManager type @@ -12,9 +20,73 @@ type EthTxManager struct { mock.Mock } -// VerifyBatch provides a mock function with given fields: batchNum, proof -func (_m *EthTxManager) VerifyBatch(batchNum uint64, proof *pb.GetProofResponse) { - _m.Called(batchNum, proof) +// Add provides a mock function with given fields: ctx, owner, id, from, to, value, data, dbTx +func (_m *EthTxManager) Add(ctx context.Context, owner string, id string, from common.Address, to *common.Address, value *big.Int, data []byte, dbTx pgx.Tx) error { + ret := _m.Called(ctx, owner, id, from, to, value, data, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, common.Address, *common.Address, *big.Int, []byte, pgx.Tx) error); ok { + r0 = rf(ctx, owner, id, from, to, value, data, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ProcessPendingMonitoredTxs provides a mock function with given fields: ctx, owner, failedResultHandler, dbTx +func (_m *EthTxManager) ProcessPendingMonitoredTxs(ctx context.Context, owner string, failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) { + _m.Called(ctx, owner, failedResultHandler, dbTx) +} + +// Result provides a mock function with given fields: ctx, owner, id, dbTx +func (_m *EthTxManager) Result(ctx context.Context, owner string, id string, dbTx pgx.Tx) (ethtxmanager.MonitoredTxResult, error) { + ret := _m.Called(ctx, owner, id, dbTx) + + var r0 ethtxmanager.MonitoredTxResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, pgx.Tx) (ethtxmanager.MonitoredTxResult, error)); ok { + return rf(ctx, owner, id, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string, pgx.Tx) ethtxmanager.MonitoredTxResult); ok { + r0 = rf(ctx, owner, id, dbTx) + } else { + r0 = ret.Get(0).(ethtxmanager.MonitoredTxResult) + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string, pgx.Tx) error); ok { + r1 = rf(ctx, owner, id, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResultsByStatus provides a mock function with given fields: ctx, owner, statuses, dbTx +func (_m *EthTxManager) ResultsByStatus(ctx context.Context, owner string, statuses []ethtxmanager.MonitoredTxStatus, dbTx pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error) { + ret := _m.Called(ctx, owner, statuses, dbTx) + + var r0 []ethtxmanager.MonitoredTxResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []ethtxmanager.MonitoredTxStatus, pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error)); ok { + return rf(ctx, owner, statuses, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []ethtxmanager.MonitoredTxStatus, pgx.Tx) []ethtxmanager.MonitoredTxResult); ok { + r0 = rf(ctx, owner, statuses, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]ethtxmanager.MonitoredTxResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []ethtxmanager.MonitoredTxStatus, pgx.Tx) error); ok { + r1 = rf(ctx, owner, statuses, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } type mockConstructorTestingTNewEthTxManager interface { diff --git a/aggregator/mocks/mock_profitabilitychecker.go b/aggregator/mocks/mock_profitabilitychecker.go new file mode 100644 index 0000000000..870e791f64 --- /dev/null +++ b/aggregator/mocks/mock_profitabilitychecker.go @@ -0,0 +1,54 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// ProfitabilityCheckerMock is an autogenerated mock type for the aggregatorTxProfitabilityChecker type +type ProfitabilityCheckerMock struct { + mock.Mock +} + +// IsProfitable provides a mock function with given fields: _a0, _a1 +func (_m *ProfitabilityCheckerMock) IsProfitable(_a0 context.Context, _a1 *big.Int) (bool, error) { + ret := _m.Called(_a0, _a1) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (bool, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) bool); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewProfitabilityCheckerMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewProfitabilityCheckerMock creates a new instance of ProfitabilityCheckerMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewProfitabilityCheckerMock(t mockConstructorTestingTNewProfitabilityCheckerMock) *ProfitabilityCheckerMock { + mock := &ProfitabilityCheckerMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/aggregator/mocks/mock_prover.go b/aggregator/mocks/mock_prover.go new file mode 100644 index 0000000000..7cba231d6e --- /dev/null +++ b/aggregator/mocks/mock_prover.go @@ -0,0 +1,224 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + pb "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" + mock "github.com/stretchr/testify/mock" +) + +// ProverMock is an autogenerated mock type for the proverInterface type +type ProverMock struct { + mock.Mock +} + +// Addr provides a mock function with given fields: +func (_m *ProverMock) Addr() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// AggregatedProof provides a mock function with given fields: inputProof1, inputProof2 +func (_m *ProverMock) AggregatedProof(inputProof1 string, inputProof2 string) (*string, error) { + ret := _m.Called(inputProof1, inputProof2) + + var r0 *string + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (*string, error)); ok { + return rf(inputProof1, inputProof2) + } + if rf, ok := ret.Get(0).(func(string, string) *string); ok { + r0 = rf(inputProof1, inputProof2) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*string) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(inputProof1, inputProof2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BatchProof provides a mock function with given fields: input +func (_m *ProverMock) BatchProof(input *pb.InputProver) (*string, error) { + ret := _m.Called(input) + + var r0 *string + var r1 error + if rf, ok := ret.Get(0).(func(*pb.InputProver) (*string, error)); ok { + return rf(input) + } + if rf, ok := ret.Get(0).(func(*pb.InputProver) *string); ok { + r0 = rf(input) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*string) + } + } + + if rf, ok := ret.Get(1).(func(*pb.InputProver) error); ok { + r1 = rf(input) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FinalProof provides a mock function with given fields: inputProof, aggregatorAddr +func (_m *ProverMock) FinalProof(inputProof string, aggregatorAddr string) (*string, error) { + ret := _m.Called(inputProof, aggregatorAddr) + + var r0 *string + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (*string, error)); ok { + return rf(inputProof, aggregatorAddr) + } + if rf, ok := ret.Get(0).(func(string, string) *string); ok { + r0 = rf(inputProof, aggregatorAddr) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*string) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(inputProof, aggregatorAddr) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ID provides a mock function with given fields: +func (_m *ProverMock) ID() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// IsIdle provides a mock function with given fields: +func (_m *ProverMock) IsIdle() (bool, error) { + ret := _m.Called() + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func() (bool, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Name provides a mock function with given fields: +func (_m *ProverMock) Name() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// WaitFinalProof provides a mock function with given fields: ctx, proofID +func (_m *ProverMock) WaitFinalProof(ctx context.Context, proofID string) (*pb.FinalProof, error) { + ret := _m.Called(ctx, proofID) + + var r0 *pb.FinalProof + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (*pb.FinalProof, error)); ok { + return rf(ctx, proofID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) *pb.FinalProof); ok { + r0 = rf(ctx, proofID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pb.FinalProof) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, proofID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// WaitRecursiveProof provides a mock function with given fields: ctx, proofID +func (_m *ProverMock) WaitRecursiveProof(ctx context.Context, proofID string) (string, error) { + ret := _m.Called(ctx, proofID) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { + return rf(ctx, proofID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { + r0 = rf(ctx, proofID) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, proofID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewProverMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewProverMock creates a new instance of ProverMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewProverMock(t mockConstructorTestingTNewProverMock) *ProverMock { + mock := &ProverMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/aggregator/mocks/mock_proverclient.go b/aggregator/mocks/mock_proverclient.go deleted file mode 100644 index 178abe31bd..0000000000 --- a/aggregator/mocks/mock_proverclient.go +++ /dev/null @@ -1,102 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - pb "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" - mock "github.com/stretchr/testify/mock" -) - -// ProverClientMock is an autogenerated mock type for the proverClientInterface type -type ProverClientMock struct { - mock.Mock -} - -// GetGenProofID provides a mock function with given fields: ctx, inputProver -func (_m *ProverClientMock) GetGenProofID(ctx context.Context, inputProver *pb.InputProver) (string, error) { - ret := _m.Called(ctx, inputProver) - - var r0 string - if rf, ok := ret.Get(0).(func(context.Context, *pb.InputProver) string); ok { - r0 = rf(ctx, inputProver) - } else { - r0 = ret.Get(0).(string) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *pb.InputProver) error); ok { - r1 = rf(ctx, inputProver) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetResGetProof provides a mock function with given fields: ctx, genProofID, batchNumber -func (_m *ProverClientMock) GetResGetProof(ctx context.Context, genProofID string, batchNumber uint64) (*pb.GetProofResponse, error) { - ret := _m.Called(ctx, genProofID, batchNumber) - - var r0 *pb.GetProofResponse - if rf, ok := ret.Get(0).(func(context.Context, string, uint64) *pb.GetProofResponse); ok { - r0 = rf(ctx, genProofID, batchNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*pb.GetProofResponse) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string, uint64) error); ok { - r1 = rf(ctx, genProofID, batchNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetURI provides a mock function with given fields: -func (_m *ProverClientMock) GetURI() string { - ret := _m.Called() - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// IsIdle provides a mock function with given fields: ctx -func (_m *ProverClientMock) IsIdle(ctx context.Context) bool { - ret := _m.Called(ctx) - - var r0 bool - if rf, ok := ret.Get(0).(func(context.Context) bool); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -type mockConstructorTestingTNewProverClientMock interface { - mock.TestingT - Cleanup(func()) -} - -// NewProverClientMock creates a new instance of ProverClientMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewProverClientMock(t mockConstructorTestingTNewProverClientMock) *ProverClientMock { - mock := &ProverClientMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/aggregator/mocks/mock_state.go b/aggregator/mocks/mock_state.go index 3aad477055..75d5e26c26 100644 --- a/aggregator/mocks/mock_state.go +++ b/aggregator/mocks/mock_state.go @@ -1,14 +1,12 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package mocks import ( context "context" - pb "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" - mock "github.com/stretchr/testify/mock" - pgx "github.com/jackc/pgx/v4" + mock "github.com/stretchr/testify/mock" state "github.com/0xPolygonHermez/zkevm-node/state" ) @@ -18,13 +16,13 @@ type StateMock struct { mock.Mock } -// AddGeneratedProof provides a mock function with given fields: ctx, batchNumber, proof, dbTx -func (_m *StateMock) AddGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error { - ret := _m.Called(ctx, batchNumber, proof, dbTx) +// AddGeneratedProof provides a mock function with given fields: ctx, proof, dbTx +func (_m *StateMock) AddGeneratedProof(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) error { + ret := _m.Called(ctx, proof, dbTx) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, *pb.GetProofResponse, pgx.Tx) error); ok { - r0 = rf(ctx, batchNumber, proof, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, *state.Proof, pgx.Tx) error); ok { + r0 = rf(ctx, proof, dbTx) } else { r0 = ret.Error(0) } @@ -32,8 +30,58 @@ func (_m *StateMock) AddGeneratedProof(ctx context.Context, batchNumber uint64, return r0 } -// DeleteGeneratedProof provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) DeleteGeneratedProof(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { +// BeginStateTransaction provides a mock function with given fields: ctx +func (_m *StateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CheckProofContainsCompleteSequences provides a mock function with given fields: ctx, proof, dbTx +func (_m *StateMock) CheckProofContainsCompleteSequences(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) (bool, error) { + ret := _m.Called(ctx, proof, dbTx) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *state.Proof, pgx.Tx) (bool, error)); ok { + return rf(ctx, proof, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, *state.Proof, pgx.Tx) bool); ok { + r0 = rf(ctx, proof, dbTx) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, *state.Proof, pgx.Tx) error); ok { + r1 = rf(ctx, proof, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CleanupGeneratedProofs provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) CleanupGeneratedProofs(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { ret := _m.Called(ctx, batchNumber, dbTx) var r0 error @@ -46,6 +94,44 @@ func (_m *StateMock) DeleteGeneratedProof(ctx context.Context, batchNumber uint6 return r0 } +// CleanupLockedProofs provides a mock function with given fields: ctx, duration, dbTx +func (_m *StateMock) CleanupLockedProofs(ctx context.Context, duration string, dbTx pgx.Tx) (int64, error) { + ret := _m.Called(ctx, duration, dbTx) + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, pgx.Tx) (int64, error)); ok { + return rf(ctx, duration, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, string, pgx.Tx) int64); ok { + r0 = rf(ctx, duration, dbTx) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, string, pgx.Tx) error); ok { + r1 = rf(ctx, duration, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteGeneratedProofs provides a mock function with given fields: ctx, batchNumber, batchNumberFinal, dbTx +func (_m *StateMock) DeleteGeneratedProofs(ctx context.Context, batchNumber uint64, batchNumberFinal uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, batchNumberFinal, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, batchNumberFinal, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // DeleteUngeneratedProofs provides a mock function with given fields: ctx, dbTx func (_m *StateMock) DeleteUngeneratedProofs(ctx context.Context, dbTx pgx.Tx) error { ret := _m.Called(ctx, dbTx) @@ -65,6 +151,10 @@ func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, d ret := _m.Called(ctx, batchNumber, dbTx) var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { r0 = rf(ctx, batchNumber, dbTx) } else { @@ -73,7 +163,6 @@ func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, d } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { r1 = rf(ctx, batchNumber, dbTx) } else { @@ -83,22 +172,51 @@ func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, d return r0, r1 } -// GetGeneratedProofByBatchNumber provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) GetGeneratedProofByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*pb.GetProofResponse, error) { - ret := _m.Called(ctx, batchNumber, dbTx) +// GetLastVerifiedBatch provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) { + ret := _m.Called(ctx, dbTx) - var r0 *pb.GetProofResponse - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *pb.GetProofResponse); ok { - r0 = rf(ctx, batchNumber, dbTx) + var r0 *state.VerifiedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.VerifiedBatch, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.VerifiedBatch); ok { + r0 = rf(ctx, dbTx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*pb.GetProofResponse) + r0 = ret.Get(0).(*state.VerifiedBatch) } } + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetProofReadyToVerify provides a mock function with given fields: ctx, lastVerfiedBatchNumber, dbTx +func (_m *StateMock) GetProofReadyToVerify(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Proof, error) { + ret := _m.Called(ctx, lastVerfiedBatchNumber, dbTx) + + var r0 *state.Proof var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Proof, error)); ok { + return rf(ctx, lastVerfiedBatchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Proof); ok { + r0 = rf(ctx, lastVerfiedBatchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Proof) + } + } + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, dbTx) + r1 = rf(ctx, lastVerfiedBatchNumber, dbTx) } else { r1 = ret.Error(1) } @@ -106,45 +224,60 @@ func (_m *StateMock) GetGeneratedProofByBatchNumber(ctx context.Context, batchNu return r0, r1 } -// GetLastVerifiedBatch provides a mock function with given fields: ctx, dbTx -func (_m *StateMock) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) { +// GetProofsToAggregate provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetProofsToAggregate(ctx context.Context, dbTx pgx.Tx) (*state.Proof, *state.Proof, error) { ret := _m.Called(ctx, dbTx) - var r0 *state.VerifiedBatch - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.VerifiedBatch); ok { + var r0 *state.Proof + var r1 *state.Proof + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Proof, *state.Proof, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Proof); ok { r0 = rf(ctx, dbTx) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*state.VerifiedBatch) + r0 = ret.Get(0).(*state.Proof) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) *state.Proof); ok { r1 = rf(ctx, dbTx) } else { - r1 = ret.Error(1) + if ret.Get(1) != nil { + r1 = ret.Get(1).(*state.Proof) + } } - return r0, r1 + if rf, ok := ret.Get(2).(func(context.Context, pgx.Tx) error); ok { + r2 = rf(ctx, dbTx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 } -// GetVirtualBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) GetVirtualBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { - ret := _m.Called(ctx, batchNumber, dbTx) +// GetVirtualBatchToProve provides a mock function with given fields: ctx, lastVerfiedBatchNumber, dbTx +func (_m *StateMock) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, lastVerfiedBatchNumber, dbTx) var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, lastVerfiedBatchNumber, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { - r0 = rf(ctx, batchNumber, dbTx) + r0 = rf(ctx, lastVerfiedBatchNumber, dbTx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*state.Batch) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, dbTx) + r1 = rf(ctx, lastVerfiedBatchNumber, dbTx) } else { r1 = ret.Error(1) } @@ -152,13 +285,13 @@ func (_m *StateMock) GetVirtualBatchByNumber(ctx context.Context, batchNumber ui return r0, r1 } -// UpdateGeneratedProof provides a mock function with given fields: ctx, batchNumber, proof, dbTx -func (_m *StateMock) UpdateGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error { - ret := _m.Called(ctx, batchNumber, proof, dbTx) +// UpdateGeneratedProof provides a mock function with given fields: ctx, proof, dbTx +func (_m *StateMock) UpdateGeneratedProof(ctx context.Context, proof *state.Proof, dbTx pgx.Tx) error { + ret := _m.Called(ctx, proof, dbTx) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, *pb.GetProofResponse, pgx.Tx) error); ok { - r0 = rf(ctx, batchNumber, proof, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, *state.Proof, pgx.Tx) error); ok { + r0 = rf(ctx, proof, dbTx) } else { r0 = ret.Error(0) } diff --git a/aggregator/pb/aggregator.pb.go b/aggregator/pb/aggregator.pb.go new file mode 100644 index 0000000000..80a24a9fea --- /dev/null +++ b/aggregator/pb/aggregator.pb.go @@ -0,0 +1,2341 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: aggregator.proto + +package pb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +//* +// @dev Result +// - OK: succesfully completed +// - ERROR: request is not correct, i.e. input data is wrong +// - INTERNAL_ERROR: internal server error when delivering the response +type Result int32 + +const ( + Result_RESULT_UNSPECIFIED Result = 0 + Result_RESULT_OK Result = 1 + Result_RESULT_ERROR Result = 2 + Result_RESULT_INTERNAL_ERROR Result = 3 +) + +// Enum value maps for Result. +var ( + Result_name = map[int32]string{ + 0: "RESULT_UNSPECIFIED", + 1: "RESULT_OK", + 2: "RESULT_ERROR", + 3: "RESULT_INTERNAL_ERROR", + } + Result_value = map[string]int32{ + "RESULT_UNSPECIFIED": 0, + "RESULT_OK": 1, + "RESULT_ERROR": 2, + "RESULT_INTERNAL_ERROR": 3, + } +) + +func (x Result) Enum() *Result { + p := new(Result) + *p = x + return p +} + +func (x Result) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Result) Descriptor() protoreflect.EnumDescriptor { + return file_aggregator_proto_enumTypes[0].Descriptor() +} + +func (Result) Type() protoreflect.EnumType { + return &file_aggregator_proto_enumTypes[0] +} + +func (x Result) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Result.Descriptor instead. +func (Result) EnumDescriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{0} +} + +type GetStatusResponse_Status int32 + +const ( + GetStatusResponse_STATUS_UNSPECIFIED GetStatusResponse_Status = 0 + GetStatusResponse_STATUS_BOOTING GetStatusResponse_Status = 1 + GetStatusResponse_STATUS_COMPUTING GetStatusResponse_Status = 2 + GetStatusResponse_STATUS_IDLE GetStatusResponse_Status = 3 + GetStatusResponse_STATUS_HALT GetStatusResponse_Status = 4 +) + +// Enum value maps for GetStatusResponse_Status. +var ( + GetStatusResponse_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "STATUS_BOOTING", + 2: "STATUS_COMPUTING", + 3: "STATUS_IDLE", + 4: "STATUS_HALT", + } + GetStatusResponse_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 0, + "STATUS_BOOTING": 1, + "STATUS_COMPUTING": 2, + "STATUS_IDLE": 3, + "STATUS_HALT": 4, + } +) + +func (x GetStatusResponse_Status) Enum() *GetStatusResponse_Status { + p := new(GetStatusResponse_Status) + *p = x + return p +} + +func (x GetStatusResponse_Status) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GetStatusResponse_Status) Descriptor() protoreflect.EnumDescriptor { + return file_aggregator_proto_enumTypes[1].Descriptor() +} + +func (GetStatusResponse_Status) Type() protoreflect.EnumType { + return &file_aggregator_proto_enumTypes[1] +} + +func (x GetStatusResponse_Status) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GetStatusResponse_Status.Descriptor instead. +func (GetStatusResponse_Status) EnumDescriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{9, 0} +} + +type GetProofResponse_Result int32 + +const ( + GetProofResponse_RESULT_UNSPECIFIED GetProofResponse_Result = 0 + GetProofResponse_RESULT_COMPLETED_OK GetProofResponse_Result = 1 + GetProofResponse_RESULT_ERROR GetProofResponse_Result = 2 + GetProofResponse_RESULT_COMPLETED_ERROR GetProofResponse_Result = 3 + GetProofResponse_RESULT_PENDING GetProofResponse_Result = 4 + GetProofResponse_RESULT_INTERNAL_ERROR GetProofResponse_Result = 5 + GetProofResponse_RESULT_CANCEL GetProofResponse_Result = 6 +) + +// Enum value maps for GetProofResponse_Result. +var ( + GetProofResponse_Result_name = map[int32]string{ + 0: "RESULT_UNSPECIFIED", + 1: "RESULT_COMPLETED_OK", + 2: "RESULT_ERROR", + 3: "RESULT_COMPLETED_ERROR", + 4: "RESULT_PENDING", + 5: "RESULT_INTERNAL_ERROR", + 6: "RESULT_CANCEL", + } + GetProofResponse_Result_value = map[string]int32{ + "RESULT_UNSPECIFIED": 0, + "RESULT_COMPLETED_OK": 1, + "RESULT_ERROR": 2, + "RESULT_COMPLETED_ERROR": 3, + "RESULT_PENDING": 4, + "RESULT_INTERNAL_ERROR": 5, + "RESULT_CANCEL": 6, + } +) + +func (x GetProofResponse_Result) Enum() *GetProofResponse_Result { + p := new(GetProofResponse_Result) + *p = x + return p +} + +func (x GetProofResponse_Result) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GetProofResponse_Result) Descriptor() protoreflect.EnumDescriptor { + return file_aggregator_proto_enumTypes[2].Descriptor() +} + +func (GetProofResponse_Result) Type() protoreflect.EnumType { + return &file_aggregator_proto_enumTypes[2] +} + +func (x GetProofResponse_Result) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GetProofResponse_Result.Descriptor instead. +func (GetProofResponse_Result) EnumDescriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{14, 0} +} + +type Version struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + V0_0_1 string `protobuf:"bytes,1,opt,name=v0_0_1,json=v001,proto3" json:"v0_0_1,omitempty"` +} + +func (x *Version) Reset() { + *x = Version{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Version) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Version) ProtoMessage() {} + +func (x *Version) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Version.ProtoReflect.Descriptor instead. +func (*Version) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{0} +} + +func (x *Version) GetV0_0_1() string { + if x != nil { + return x.V0_0_1 + } + return "" +} + +type AggregatorMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Types that are assignable to Request: + // *AggregatorMessage_GetStatusRequest + // *AggregatorMessage_GenBatchProofRequest + // *AggregatorMessage_GenAggregatedProofRequest + // *AggregatorMessage_GenFinalProofRequest + // *AggregatorMessage_CancelRequest + // *AggregatorMessage_GetProofRequest + Request isAggregatorMessage_Request `protobuf_oneof:"request"` +} + +func (x *AggregatorMessage) Reset() { + *x = AggregatorMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AggregatorMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AggregatorMessage) ProtoMessage() {} + +func (x *AggregatorMessage) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AggregatorMessage.ProtoReflect.Descriptor instead. +func (*AggregatorMessage) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{1} +} + +func (x *AggregatorMessage) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (m *AggregatorMessage) GetRequest() isAggregatorMessage_Request { + if m != nil { + return m.Request + } + return nil +} + +func (x *AggregatorMessage) GetGetStatusRequest() *GetStatusRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_GetStatusRequest); ok { + return x.GetStatusRequest + } + return nil +} + +func (x *AggregatorMessage) GetGenBatchProofRequest() *GenBatchProofRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_GenBatchProofRequest); ok { + return x.GenBatchProofRequest + } + return nil +} + +func (x *AggregatorMessage) GetGenAggregatedProofRequest() *GenAggregatedProofRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_GenAggregatedProofRequest); ok { + return x.GenAggregatedProofRequest + } + return nil +} + +func (x *AggregatorMessage) GetGenFinalProofRequest() *GenFinalProofRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_GenFinalProofRequest); ok { + return x.GenFinalProofRequest + } + return nil +} + +func (x *AggregatorMessage) GetCancelRequest() *CancelRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_CancelRequest); ok { + return x.CancelRequest + } + return nil +} + +func (x *AggregatorMessage) GetGetProofRequest() *GetProofRequest { + if x, ok := x.GetRequest().(*AggregatorMessage_GetProofRequest); ok { + return x.GetProofRequest + } + return nil +} + +type isAggregatorMessage_Request interface { + isAggregatorMessage_Request() +} + +type AggregatorMessage_GetStatusRequest struct { + GetStatusRequest *GetStatusRequest `protobuf:"bytes,2,opt,name=get_status_request,json=getStatusRequest,proto3,oneof"` +} + +type AggregatorMessage_GenBatchProofRequest struct { + GenBatchProofRequest *GenBatchProofRequest `protobuf:"bytes,3,opt,name=gen_batch_proof_request,json=genBatchProofRequest,proto3,oneof"` +} + +type AggregatorMessage_GenAggregatedProofRequest struct { + GenAggregatedProofRequest *GenAggregatedProofRequest `protobuf:"bytes,4,opt,name=gen_aggregated_proof_request,json=genAggregatedProofRequest,proto3,oneof"` +} + +type AggregatorMessage_GenFinalProofRequest struct { + GenFinalProofRequest *GenFinalProofRequest `protobuf:"bytes,5,opt,name=gen_final_proof_request,json=genFinalProofRequest,proto3,oneof"` +} + +type AggregatorMessage_CancelRequest struct { + CancelRequest *CancelRequest `protobuf:"bytes,6,opt,name=cancel_request,json=cancelRequest,proto3,oneof"` +} + +type AggregatorMessage_GetProofRequest struct { + GetProofRequest *GetProofRequest `protobuf:"bytes,7,opt,name=get_proof_request,json=getProofRequest,proto3,oneof"` +} + +func (*AggregatorMessage_GetStatusRequest) isAggregatorMessage_Request() {} + +func (*AggregatorMessage_GenBatchProofRequest) isAggregatorMessage_Request() {} + +func (*AggregatorMessage_GenAggregatedProofRequest) isAggregatorMessage_Request() {} + +func (*AggregatorMessage_GenFinalProofRequest) isAggregatorMessage_Request() {} + +func (*AggregatorMessage_CancelRequest) isAggregatorMessage_Request() {} + +func (*AggregatorMessage_GetProofRequest) isAggregatorMessage_Request() {} + +type ProverMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Types that are assignable to Response: + // *ProverMessage_GetStatusResponse + // *ProverMessage_GenBatchProofResponse + // *ProverMessage_GenAggregatedProofResponse + // *ProverMessage_GenFinalProofResponse + // *ProverMessage_CancelResponse + // *ProverMessage_GetProofResponse + Response isProverMessage_Response `protobuf_oneof:"response"` +} + +func (x *ProverMessage) Reset() { + *x = ProverMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProverMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProverMessage) ProtoMessage() {} + +func (x *ProverMessage) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProverMessage.ProtoReflect.Descriptor instead. +func (*ProverMessage) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{2} +} + +func (x *ProverMessage) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (m *ProverMessage) GetResponse() isProverMessage_Response { + if m != nil { + return m.Response + } + return nil +} + +func (x *ProverMessage) GetGetStatusResponse() *GetStatusResponse { + if x, ok := x.GetResponse().(*ProverMessage_GetStatusResponse); ok { + return x.GetStatusResponse + } + return nil +} + +func (x *ProverMessage) GetGenBatchProofResponse() *GenBatchProofResponse { + if x, ok := x.GetResponse().(*ProverMessage_GenBatchProofResponse); ok { + return x.GenBatchProofResponse + } + return nil +} + +func (x *ProverMessage) GetGenAggregatedProofResponse() *GenAggregatedProofResponse { + if x, ok := x.GetResponse().(*ProverMessage_GenAggregatedProofResponse); ok { + return x.GenAggregatedProofResponse + } + return nil +} + +func (x *ProverMessage) GetGenFinalProofResponse() *GenFinalProofResponse { + if x, ok := x.GetResponse().(*ProverMessage_GenFinalProofResponse); ok { + return x.GenFinalProofResponse + } + return nil +} + +func (x *ProverMessage) GetCancelResponse() *CancelResponse { + if x, ok := x.GetResponse().(*ProverMessage_CancelResponse); ok { + return x.CancelResponse + } + return nil +} + +func (x *ProverMessage) GetGetProofResponse() *GetProofResponse { + if x, ok := x.GetResponse().(*ProverMessage_GetProofResponse); ok { + return x.GetProofResponse + } + return nil +} + +type isProverMessage_Response interface { + isProverMessage_Response() +} + +type ProverMessage_GetStatusResponse struct { + GetStatusResponse *GetStatusResponse `protobuf:"bytes,2,opt,name=get_status_response,json=getStatusResponse,proto3,oneof"` +} + +type ProverMessage_GenBatchProofResponse struct { + GenBatchProofResponse *GenBatchProofResponse `protobuf:"bytes,3,opt,name=gen_batch_proof_response,json=genBatchProofResponse,proto3,oneof"` +} + +type ProverMessage_GenAggregatedProofResponse struct { + GenAggregatedProofResponse *GenAggregatedProofResponse `protobuf:"bytes,4,opt,name=gen_aggregated_proof_response,json=genAggregatedProofResponse,proto3,oneof"` +} + +type ProverMessage_GenFinalProofResponse struct { + GenFinalProofResponse *GenFinalProofResponse `protobuf:"bytes,5,opt,name=gen_final_proof_response,json=genFinalProofResponse,proto3,oneof"` +} + +type ProverMessage_CancelResponse struct { + CancelResponse *CancelResponse `protobuf:"bytes,6,opt,name=cancel_response,json=cancelResponse,proto3,oneof"` +} + +type ProverMessage_GetProofResponse struct { + GetProofResponse *GetProofResponse `protobuf:"bytes,7,opt,name=get_proof_response,json=getProofResponse,proto3,oneof"` +} + +func (*ProverMessage_GetStatusResponse) isProverMessage_Response() {} + +func (*ProverMessage_GenBatchProofResponse) isProverMessage_Response() {} + +func (*ProverMessage_GenAggregatedProofResponse) isProverMessage_Response() {} + +func (*ProverMessage_GenFinalProofResponse) isProverMessage_Response() {} + +func (*ProverMessage_CancelResponse) isProverMessage_Response() {} + +func (*ProverMessage_GetProofResponse) isProverMessage_Response() {} + +//* +// @dev GetStatusRequest +type GetStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetStatusRequest) Reset() { + *x = GetStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStatusRequest) ProtoMessage() {} + +func (x *GetStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStatusRequest.ProtoReflect.Descriptor instead. +func (*GetStatusRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{3} +} + +//* +// @dev GenBatchProofRequest +// @param {input} - input prover +type GenBatchProofRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Input *InputProver `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` +} + +func (x *GenBatchProofRequest) Reset() { + *x = GenBatchProofRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenBatchProofRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenBatchProofRequest) ProtoMessage() {} + +func (x *GenBatchProofRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenBatchProofRequest.ProtoReflect.Descriptor instead. +func (*GenBatchProofRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{4} +} + +func (x *GenBatchProofRequest) GetInput() *InputProver { + if x != nil { + return x.Input + } + return nil +} + +//* +// @dev GenAggregatedProofRequest +// @param {recursive_proof_1} - proof json of the first batch to aggregate +// @param {recursive_proof_2} - proof json of the second batch to aggregate +type GenAggregatedProofRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RecursiveProof_1 string `protobuf:"bytes,1,opt,name=recursive_proof_1,json=recursiveProof1,proto3" json:"recursive_proof_1,omitempty"` + RecursiveProof_2 string `protobuf:"bytes,2,opt,name=recursive_proof_2,json=recursiveProof2,proto3" json:"recursive_proof_2,omitempty"` +} + +func (x *GenAggregatedProofRequest) Reset() { + *x = GenAggregatedProofRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenAggregatedProofRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenAggregatedProofRequest) ProtoMessage() {} + +func (x *GenAggregatedProofRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenAggregatedProofRequest.ProtoReflect.Descriptor instead. +func (*GenAggregatedProofRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{5} +} + +func (x *GenAggregatedProofRequest) GetRecursiveProof_1() string { + if x != nil { + return x.RecursiveProof_1 + } + return "" +} + +func (x *GenAggregatedProofRequest) GetRecursiveProof_2() string { + if x != nil { + return x.RecursiveProof_2 + } + return "" +} + +//* +// @dev GenFinalProofRequest +// @param {recursive_proof} - proof json of the batch or aggregated proof to finalise +// @param {aggregator_addr} - address of the aggregator +type GenFinalProofRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RecursiveProof string `protobuf:"bytes,1,opt,name=recursive_proof,json=recursiveProof,proto3" json:"recursive_proof,omitempty"` + AggregatorAddr string `protobuf:"bytes,2,opt,name=aggregator_addr,json=aggregatorAddr,proto3" json:"aggregator_addr,omitempty"` +} + +func (x *GenFinalProofRequest) Reset() { + *x = GenFinalProofRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenFinalProofRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenFinalProofRequest) ProtoMessage() {} + +func (x *GenFinalProofRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenFinalProofRequest.ProtoReflect.Descriptor instead. +func (*GenFinalProofRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{6} +} + +func (x *GenFinalProofRequest) GetRecursiveProof() string { + if x != nil { + return x.RecursiveProof + } + return "" +} + +func (x *GenFinalProofRequest) GetAggregatorAddr() string { + if x != nil { + return x.AggregatorAddr + } + return "" +} + +//* +// @dev CancelRequest +// @param {id} - identifier of the proof request to cancel +type CancelRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *CancelRequest) Reset() { + *x = CancelRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CancelRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelRequest) ProtoMessage() {} + +func (x *CancelRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CancelRequest.ProtoReflect.Descriptor instead. +func (*CancelRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{7} +} + +func (x *CancelRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +//* +// @dev Request GetProof +// @param {id} - proof identifier of the proof request +// @param {timeout} - time to wait until the service responds +type GetProofRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Timeout uint64 `protobuf:"varint,2,opt,name=timeout,proto3" json:"timeout,omitempty"` +} + +func (x *GetProofRequest) Reset() { + *x = GetProofRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetProofRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProofRequest) ProtoMessage() {} + +func (x *GetProofRequest) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetProofRequest.ProtoReflect.Descriptor instead. +func (*GetProofRequest) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{8} +} + +func (x *GetProofRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GetProofRequest) GetTimeout() uint64 { + if x != nil { + return x.Timeout + } + return 0 +} + +//* +// @dev Response GetStatus +// @param {status} - server status +// - BOOTING: being ready to compute proofs +// - COMPUTING: busy computing a proof +// - IDLE: waiting for a proof to compute +// - HALT: stop +// @param {last_computed_request_id} - last proof identifier that has been computed +// @param {last_computed_end_time} - last proof timestamp when it was finished +// @param {current_computing_request_id} - id of the proof that is being computed +// @param {current_computing_start_time} - timestamp when the proof that is being computed started +// @param {version_proto} - .proto verion +// @param {version_server} - server version +// @param {pending_request_queue_ids} - list of identifierss of proof requests that are in the pending queue +// @param {prover_name} - id of this prover server, normally specified via config.json, or UNSPECIFIED otherwise; it does not change if prover reboots +// @param {prover_id} - id of this prover instance or reboot; it changes if prover reboots; it is a UUID, automatically generated during the initialization +// @param {number_of_cores} - number of cores in the system where the prover is running +// @param {total_memory} - total memory in the system where the prover is running +// @param {free_memory} - free memory in the system where the prover is running +type GetStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status GetStatusResponse_Status `protobuf:"varint,1,opt,name=status,proto3,enum=aggregator.v1.GetStatusResponse_Status" json:"status,omitempty"` + LastComputedRequestId string `protobuf:"bytes,2,opt,name=last_computed_request_id,json=lastComputedRequestId,proto3" json:"last_computed_request_id,omitempty"` + LastComputedEndTime uint64 `protobuf:"varint,3,opt,name=last_computed_end_time,json=lastComputedEndTime,proto3" json:"last_computed_end_time,omitempty"` + CurrentComputingRequestId string `protobuf:"bytes,4,opt,name=current_computing_request_id,json=currentComputingRequestId,proto3" json:"current_computing_request_id,omitempty"` + CurrentComputingStartTime uint64 `protobuf:"varint,5,opt,name=current_computing_start_time,json=currentComputingStartTime,proto3" json:"current_computing_start_time,omitempty"` + VersionProto string `protobuf:"bytes,6,opt,name=version_proto,json=versionProto,proto3" json:"version_proto,omitempty"` + VersionServer string `protobuf:"bytes,7,opt,name=version_server,json=versionServer,proto3" json:"version_server,omitempty"` + PendingRequestQueueIds []string `protobuf:"bytes,8,rep,name=pending_request_queue_ids,json=pendingRequestQueueIds,proto3" json:"pending_request_queue_ids,omitempty"` + ProverName string `protobuf:"bytes,9,opt,name=prover_name,json=proverName,proto3" json:"prover_name,omitempty"` + ProverId string `protobuf:"bytes,10,opt,name=prover_id,json=proverId,proto3" json:"prover_id,omitempty"` + NumberOfCores uint64 `protobuf:"varint,11,opt,name=number_of_cores,json=numberOfCores,proto3" json:"number_of_cores,omitempty"` + TotalMemory uint64 `protobuf:"varint,12,opt,name=total_memory,json=totalMemory,proto3" json:"total_memory,omitempty"` + FreeMemory uint64 `protobuf:"varint,13,opt,name=free_memory,json=freeMemory,proto3" json:"free_memory,omitempty"` + ForkId uint64 `protobuf:"varint,14,opt,name=fork_id,json=forkId,proto3" json:"fork_id,omitempty"` +} + +func (x *GetStatusResponse) Reset() { + *x = GetStatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetStatusResponse) ProtoMessage() {} + +func (x *GetStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetStatusResponse.ProtoReflect.Descriptor instead. +func (*GetStatusResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{9} +} + +func (x *GetStatusResponse) GetStatus() GetStatusResponse_Status { + if x != nil { + return x.Status + } + return GetStatusResponse_STATUS_UNSPECIFIED +} + +func (x *GetStatusResponse) GetLastComputedRequestId() string { + if x != nil { + return x.LastComputedRequestId + } + return "" +} + +func (x *GetStatusResponse) GetLastComputedEndTime() uint64 { + if x != nil { + return x.LastComputedEndTime + } + return 0 +} + +func (x *GetStatusResponse) GetCurrentComputingRequestId() string { + if x != nil { + return x.CurrentComputingRequestId + } + return "" +} + +func (x *GetStatusResponse) GetCurrentComputingStartTime() uint64 { + if x != nil { + return x.CurrentComputingStartTime + } + return 0 +} + +func (x *GetStatusResponse) GetVersionProto() string { + if x != nil { + return x.VersionProto + } + return "" +} + +func (x *GetStatusResponse) GetVersionServer() string { + if x != nil { + return x.VersionServer + } + return "" +} + +func (x *GetStatusResponse) GetPendingRequestQueueIds() []string { + if x != nil { + return x.PendingRequestQueueIds + } + return nil +} + +func (x *GetStatusResponse) GetProverName() string { + if x != nil { + return x.ProverName + } + return "" +} + +func (x *GetStatusResponse) GetProverId() string { + if x != nil { + return x.ProverId + } + return "" +} + +func (x *GetStatusResponse) GetNumberOfCores() uint64 { + if x != nil { + return x.NumberOfCores + } + return 0 +} + +func (x *GetStatusResponse) GetTotalMemory() uint64 { + if x != nil { + return x.TotalMemory + } + return 0 +} + +func (x *GetStatusResponse) GetFreeMemory() uint64 { + if x != nil { + return x.FreeMemory + } + return 0 +} + +func (x *GetStatusResponse) GetForkId() uint64 { + if x != nil { + return x.ForkId + } + return 0 +} + +//* +// @dev GenBatchProofResponse +// @param {id} - proof identifier, to be used in GetProofRequest() +// @param {result} - request result +type GenBatchProofResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Result Result `protobuf:"varint,2,opt,name=result,proto3,enum=aggregator.v1.Result" json:"result,omitempty"` +} + +func (x *GenBatchProofResponse) Reset() { + *x = GenBatchProofResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenBatchProofResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenBatchProofResponse) ProtoMessage() {} + +func (x *GenBatchProofResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenBatchProofResponse.ProtoReflect.Descriptor instead. +func (*GenBatchProofResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{10} +} + +func (x *GenBatchProofResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GenBatchProofResponse) GetResult() Result { + if x != nil { + return x.Result + } + return Result_RESULT_UNSPECIFIED +} + +//* +// @dev GenAggregatedProofResponse +// @param {id} - proof identifier, to be used in GetProofRequest() +// @param {result} - request result +type GenAggregatedProofResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Result Result `protobuf:"varint,2,opt,name=result,proto3,enum=aggregator.v1.Result" json:"result,omitempty"` +} + +func (x *GenAggregatedProofResponse) Reset() { + *x = GenAggregatedProofResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenAggregatedProofResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenAggregatedProofResponse) ProtoMessage() {} + +func (x *GenAggregatedProofResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenAggregatedProofResponse.ProtoReflect.Descriptor instead. +func (*GenAggregatedProofResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{11} +} + +func (x *GenAggregatedProofResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GenAggregatedProofResponse) GetResult() Result { + if x != nil { + return x.Result + } + return Result_RESULT_UNSPECIFIED +} + +//* +// @dev Response GenFinalProof +// @param {id} - proof identifier, to be used in GetProofRequest() +// @param {result} - request result +type GenFinalProofResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Result Result `protobuf:"varint,2,opt,name=result,proto3,enum=aggregator.v1.Result" json:"result,omitempty"` +} + +func (x *GenFinalProofResponse) Reset() { + *x = GenFinalProofResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenFinalProofResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenFinalProofResponse) ProtoMessage() {} + +func (x *GenFinalProofResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenFinalProofResponse.ProtoReflect.Descriptor instead. +func (*GenFinalProofResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{12} +} + +func (x *GenFinalProofResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GenFinalProofResponse) GetResult() Result { + if x != nil { + return x.Result + } + return Result_RESULT_UNSPECIFIED +} + +//* +// @dev CancelResponse +// @param {result} - request result +type CancelResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result Result `protobuf:"varint,1,opt,name=result,proto3,enum=aggregator.v1.Result" json:"result,omitempty"` +} + +func (x *CancelResponse) Reset() { + *x = CancelResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CancelResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CancelResponse) ProtoMessage() {} + +func (x *CancelResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CancelResponse.ProtoReflect.Descriptor instead. +func (*CancelResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{13} +} + +func (x *CancelResponse) GetResult() Result { + if x != nil { + return x.Result + } + return Result_RESULT_UNSPECIFIED +} + +//* +// @dev GetProofResponse +// @param {id} - proof identifier +// @param {final_proof} - groth16 proof + public circuit inputs +// @param {recursive_proof} - recursive proof json +// @param {result} - proof result +// - COMPLETED_OK: proof has been computed successfully and it is valid +// - ERROR: request error +// - COMPLETED_ERROR: proof has been computed successfully and it is not valid +// - PENDING: proof is being computed +// - INTERNAL_ERROR: server error during proof computation +// - CANCEL: proof has been cancelled +// @param {result_string} - extends result information +type GetProofResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Types that are assignable to Proof: + // *GetProofResponse_FinalProof + // *GetProofResponse_RecursiveProof + Proof isGetProofResponse_Proof `protobuf_oneof:"proof"` + Result GetProofResponse_Result `protobuf:"varint,4,opt,name=result,proto3,enum=aggregator.v1.GetProofResponse_Result" json:"result,omitempty"` + ResultString string `protobuf:"bytes,5,opt,name=result_string,json=resultString,proto3" json:"result_string,omitempty"` +} + +func (x *GetProofResponse) Reset() { + *x = GetProofResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetProofResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProofResponse) ProtoMessage() {} + +func (x *GetProofResponse) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetProofResponse.ProtoReflect.Descriptor instead. +func (*GetProofResponse) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{14} +} + +func (x *GetProofResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (m *GetProofResponse) GetProof() isGetProofResponse_Proof { + if m != nil { + return m.Proof + } + return nil +} + +func (x *GetProofResponse) GetFinalProof() *FinalProof { + if x, ok := x.GetProof().(*GetProofResponse_FinalProof); ok { + return x.FinalProof + } + return nil +} + +func (x *GetProofResponse) GetRecursiveProof() string { + if x, ok := x.GetProof().(*GetProofResponse_RecursiveProof); ok { + return x.RecursiveProof + } + return "" +} + +func (x *GetProofResponse) GetResult() GetProofResponse_Result { + if x != nil { + return x.Result + } + return GetProofResponse_RESULT_UNSPECIFIED +} + +func (x *GetProofResponse) GetResultString() string { + if x != nil { + return x.ResultString + } + return "" +} + +type isGetProofResponse_Proof interface { + isGetProofResponse_Proof() +} + +type GetProofResponse_FinalProof struct { + FinalProof *FinalProof `protobuf:"bytes,2,opt,name=final_proof,json=finalProof,proto3,oneof"` +} + +type GetProofResponse_RecursiveProof struct { + RecursiveProof string `protobuf:"bytes,3,opt,name=recursive_proof,json=recursiveProof,proto3,oneof"` +} + +func (*GetProofResponse_FinalProof) isGetProofResponse_Proof() {} + +func (*GetProofResponse_RecursiveProof) isGetProofResponse_Proof() {} + +// +// @dev FinalProof +// @param {proof} - groth16 proof +// @param {public} - public circuit inputs +type FinalProof struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Proof string `protobuf:"bytes,1,opt,name=proof,proto3" json:"proof,omitempty"` + Public *PublicInputsExtended `protobuf:"bytes,2,opt,name=public,proto3" json:"public,omitempty"` +} + +func (x *FinalProof) Reset() { + *x = FinalProof{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FinalProof) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinalProof) ProtoMessage() {} + +func (x *FinalProof) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FinalProof.ProtoReflect.Descriptor instead. +func (*FinalProof) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{15} +} + +func (x *FinalProof) GetProof() string { + if x != nil { + return x.Proof + } + return "" +} + +func (x *FinalProof) GetPublic() *PublicInputsExtended { + if x != nil { + return x.Public + } + return nil +} + +// +// @dev PublicInputs +// @param {old_state_root} +// @param {old_acc_input_hash} +// @param {old_batch_num} +// @param {chain_id} +// @param {batch_l2_data} +// @param {global_exit_root} +// @param {sequencer_addr} +// @param {aggregator_addr} +type PublicInputs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OldStateRoot []byte `protobuf:"bytes,1,opt,name=old_state_root,json=oldStateRoot,proto3" json:"old_state_root,omitempty"` + OldAccInputHash []byte `protobuf:"bytes,2,opt,name=old_acc_input_hash,json=oldAccInputHash,proto3" json:"old_acc_input_hash,omitempty"` + OldBatchNum uint64 `protobuf:"varint,3,opt,name=old_batch_num,json=oldBatchNum,proto3" json:"old_batch_num,omitempty"` + ChainId uint64 `protobuf:"varint,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ForkId uint64 `protobuf:"varint,5,opt,name=fork_id,json=forkId,proto3" json:"fork_id,omitempty"` + BatchL2Data []byte `protobuf:"bytes,6,opt,name=batch_l2_data,json=batchL2Data,proto3" json:"batch_l2_data,omitempty"` + GlobalExitRoot []byte `protobuf:"bytes,7,opt,name=global_exit_root,json=globalExitRoot,proto3" json:"global_exit_root,omitempty"` + EthTimestamp uint64 `protobuf:"varint,8,opt,name=eth_timestamp,json=ethTimestamp,proto3" json:"eth_timestamp,omitempty"` + SequencerAddr string `protobuf:"bytes,9,opt,name=sequencer_addr,json=sequencerAddr,proto3" json:"sequencer_addr,omitempty"` + AggregatorAddr string `protobuf:"bytes,10,opt,name=aggregator_addr,json=aggregatorAddr,proto3" json:"aggregator_addr,omitempty"` +} + +func (x *PublicInputs) Reset() { + *x = PublicInputs{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicInputs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicInputs) ProtoMessage() {} + +func (x *PublicInputs) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PublicInputs.ProtoReflect.Descriptor instead. +func (*PublicInputs) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{16} +} + +func (x *PublicInputs) GetOldStateRoot() []byte { + if x != nil { + return x.OldStateRoot + } + return nil +} + +func (x *PublicInputs) GetOldAccInputHash() []byte { + if x != nil { + return x.OldAccInputHash + } + return nil +} + +func (x *PublicInputs) GetOldBatchNum() uint64 { + if x != nil { + return x.OldBatchNum + } + return 0 +} + +func (x *PublicInputs) GetChainId() uint64 { + if x != nil { + return x.ChainId + } + return 0 +} + +func (x *PublicInputs) GetForkId() uint64 { + if x != nil { + return x.ForkId + } + return 0 +} + +func (x *PublicInputs) GetBatchL2Data() []byte { + if x != nil { + return x.BatchL2Data + } + return nil +} + +func (x *PublicInputs) GetGlobalExitRoot() []byte { + if x != nil { + return x.GlobalExitRoot + } + return nil +} + +func (x *PublicInputs) GetEthTimestamp() uint64 { + if x != nil { + return x.EthTimestamp + } + return 0 +} + +func (x *PublicInputs) GetSequencerAddr() string { + if x != nil { + return x.SequencerAddr + } + return "" +} + +func (x *PublicInputs) GetAggregatorAddr() string { + if x != nil { + return x.AggregatorAddr + } + return "" +} + +//* +// @dev InputProver +// @param {public_inputs} - public inputs +// @param {db} - database containing all key-values in smt matching the old state root +// @param {contracts_bytecode} - key is the hash(contractBytecode), value is the bytecode itself +type InputProver struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PublicInputs *PublicInputs `protobuf:"bytes,1,opt,name=public_inputs,json=publicInputs,proto3" json:"public_inputs,omitempty"` + Db map[string]string `protobuf:"bytes,4,rep,name=db,proto3" json:"db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production + ContractsBytecode map[string]string `protobuf:"bytes,5,rep,name=contracts_bytecode,json=contractsBytecode,proto3" json:"contracts_bytecode,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production +} + +func (x *InputProver) Reset() { + *x = InputProver{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InputProver) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InputProver) ProtoMessage() {} + +func (x *InputProver) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InputProver.ProtoReflect.Descriptor instead. +func (*InputProver) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{17} +} + +func (x *InputProver) GetPublicInputs() *PublicInputs { + if x != nil { + return x.PublicInputs + } + return nil +} + +func (x *InputProver) GetDb() map[string]string { + if x != nil { + return x.Db + } + return nil +} + +func (x *InputProver) GetContractsBytecode() map[string]string { + if x != nil { + return x.ContractsBytecode + } + return nil +} + +//* +// @dev PublicInputsExtended +// @param {public_inputs} - public inputs +// @param {new_state_root} - final state root. Used as a sanity check. +// @param {new_acc_input_hash} - final accumulate input hash. Used as a sanity check. +// @param {new_local_exit_root} - new local exit root. Used as a sanity check. +// @param {new_batch_num} - final num batch. Used as a sanity check. +type PublicInputsExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PublicInputs *PublicInputs `protobuf:"bytes,1,opt,name=public_inputs,json=publicInputs,proto3" json:"public_inputs,omitempty"` + NewStateRoot []byte `protobuf:"bytes,2,opt,name=new_state_root,json=newStateRoot,proto3" json:"new_state_root,omitempty"` + NewAccInputHash []byte `protobuf:"bytes,3,opt,name=new_acc_input_hash,json=newAccInputHash,proto3" json:"new_acc_input_hash,omitempty"` + NewLocalExitRoot []byte `protobuf:"bytes,4,opt,name=new_local_exit_root,json=newLocalExitRoot,proto3" json:"new_local_exit_root,omitempty"` + NewBatchNum uint64 `protobuf:"varint,5,opt,name=new_batch_num,json=newBatchNum,proto3" json:"new_batch_num,omitempty"` +} + +func (x *PublicInputsExtended) Reset() { + *x = PublicInputsExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_aggregator_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicInputsExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicInputsExtended) ProtoMessage() {} + +func (x *PublicInputsExtended) ProtoReflect() protoreflect.Message { + mi := &file_aggregator_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PublicInputsExtended.ProtoReflect.Descriptor instead. +func (*PublicInputsExtended) Descriptor() ([]byte, []int) { + return file_aggregator_proto_rawDescGZIP(), []int{18} +} + +func (x *PublicInputsExtended) GetPublicInputs() *PublicInputs { + if x != nil { + return x.PublicInputs + } + return nil +} + +func (x *PublicInputsExtended) GetNewStateRoot() []byte { + if x != nil { + return x.NewStateRoot + } + return nil +} + +func (x *PublicInputsExtended) GetNewAccInputHash() []byte { + if x != nil { + return x.NewAccInputHash + } + return nil +} + +func (x *PublicInputsExtended) GetNewLocalExitRoot() []byte { + if x != nil { + return x.NewLocalExitRoot + } + return nil +} + +func (x *PublicInputsExtended) GetNewBatchNum() uint64 { + if x != nil { + return x.NewBatchNum + } + return 0 +} + +var File_aggregator_proto protoreflect.FileDescriptor + +var file_aggregator_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x22, 0x1f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x06, + 0x76, 0x30, 0x5f, 0x30, 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x30, + 0x30, 0x31, 0x22, 0xbd, 0x04, 0x0a, 0x11, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x4f, 0x0a, 0x12, 0x67, 0x65, 0x74, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x10, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x17, 0x67, 0x65, 0x6e, + 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, + 0x00, 0x52, 0x14, 0x67, 0x65, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6b, 0x0a, 0x1c, 0x67, 0x65, 0x6e, 0x5f, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x6e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x19, 0x67, 0x65, 0x6e, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x5f, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x67, 0x65, + 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x45, 0x0a, 0x0e, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x63, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x11, 0x67, 0x65, 0x74, + 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x67, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0xcc, 0x04, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x11, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x67, 0x65, 0x6e, 0x5f, + 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x48, 0x00, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x1d, 0x67, 0x65, 0x6e, + 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x6e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1a, 0x67, + 0x65, 0x6e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x67, 0x65, 0x6e, + 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x46, + 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x10, 0x67, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, + 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, + 0x73, 0x0a, 0x19, 0x47, 0x65, 0x6e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x11, + 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, + 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, + 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x31, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x75, + 0x72, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x32, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x32, 0x22, 0x68, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, + 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x22, 0x1f, + 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, + 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0xfc, 0x05, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, + 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, + 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, + 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x12, 0x3f, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, + 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x0a, 0x0e, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x39, 0x0a, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4f, 0x66, 0x43, 0x6f, 0x72, 0x65, 0x73, + 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x65, 0x6d, + 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x72, 0x65, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x66, 0x72, 0x65, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x22, 0x6c, 0x0a, + 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x49, 0x4e, + 0x47, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, + 0x4d, 0x50, 0x55, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x48, 0x41, 0x4c, 0x54, 0x10, 0x04, 0x22, 0x56, 0x0a, 0x15, 0x47, + 0x65, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x22, 0x5b, 0x0a, 0x1a, 0x47, 0x65, 0x6e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x22, 0x56, 0x0a, 0x15, 0x47, 0x65, 0x6e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3f, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0xa5, 0x03, 0x0a, 0x10, 0x47, 0x65, + 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3c, + 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, + 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x29, 0x0a, 0x0f, + 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, + 0x76, 0x65, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x3e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0xa9, 0x01, 0x0a, + 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x55, 0x4c, + 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, + 0x54, 0x45, 0x44, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x53, 0x55, + 0x4c, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, + 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, + 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, + 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, + 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x10, 0x06, 0x42, 0x07, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x22, 0x5f, 0x0a, 0x0a, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, + 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x3b, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, + 0x74, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x22, 0xfc, 0x02, 0x0a, 0x0c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6f, 0x6c, 0x64, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x6f, 0x6c, 0x64, + 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6f, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6c, 0x64, 0x5f, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6f, + 0x6c, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x22, + 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x32, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x32, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, + 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x0d, + 0x65, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0c, 0x65, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x71, 0x75, 0x65, + 0x6e, 0x63, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, + 0x72, 0x22, 0xe2, 0x02, 0x0a, 0x0b, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, + 0x72, 0x12, 0x40, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x73, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x44, 0x62, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x02, 0x64, 0x62, 0x12, 0x60, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x1a, 0x35, 0x0a, 0x07, 0x44, 0x62, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, + 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfe, 0x01, 0x0a, 0x14, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, + 0x40, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x73, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, + 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x6e, 0x65, 0x77, 0x5f, 0x61, + 0x63, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x41, 0x63, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, + 0x6f, 0x6f, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x65, 0x77, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x2a, 0x5c, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x53, + 0x55, 0x4c, 0x54, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x53, 0x55, + 0x4c, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, + 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x03, 0x32, 0x64, 0x0a, 0x11, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x07, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x1a, 0x20, 0x2e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x35, 0x5a, 0x33, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79, + 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x2f, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_aggregator_proto_rawDescOnce sync.Once + file_aggregator_proto_rawDescData = file_aggregator_proto_rawDesc +) + +func file_aggregator_proto_rawDescGZIP() []byte { + file_aggregator_proto_rawDescOnce.Do(func() { + file_aggregator_proto_rawDescData = protoimpl.X.CompressGZIP(file_aggregator_proto_rawDescData) + }) + return file_aggregator_proto_rawDescData +} + +var file_aggregator_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_aggregator_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_aggregator_proto_goTypes = []interface{}{ + (Result)(0), // 0: aggregator.v1.Result + (GetStatusResponse_Status)(0), // 1: aggregator.v1.GetStatusResponse.Status + (GetProofResponse_Result)(0), // 2: aggregator.v1.GetProofResponse.Result + (*Version)(nil), // 3: aggregator.v1.Version + (*AggregatorMessage)(nil), // 4: aggregator.v1.AggregatorMessage + (*ProverMessage)(nil), // 5: aggregator.v1.ProverMessage + (*GetStatusRequest)(nil), // 6: aggregator.v1.GetStatusRequest + (*GenBatchProofRequest)(nil), // 7: aggregator.v1.GenBatchProofRequest + (*GenAggregatedProofRequest)(nil), // 8: aggregator.v1.GenAggregatedProofRequest + (*GenFinalProofRequest)(nil), // 9: aggregator.v1.GenFinalProofRequest + (*CancelRequest)(nil), // 10: aggregator.v1.CancelRequest + (*GetProofRequest)(nil), // 11: aggregator.v1.GetProofRequest + (*GetStatusResponse)(nil), // 12: aggregator.v1.GetStatusResponse + (*GenBatchProofResponse)(nil), // 13: aggregator.v1.GenBatchProofResponse + (*GenAggregatedProofResponse)(nil), // 14: aggregator.v1.GenAggregatedProofResponse + (*GenFinalProofResponse)(nil), // 15: aggregator.v1.GenFinalProofResponse + (*CancelResponse)(nil), // 16: aggregator.v1.CancelResponse + (*GetProofResponse)(nil), // 17: aggregator.v1.GetProofResponse + (*FinalProof)(nil), // 18: aggregator.v1.FinalProof + (*PublicInputs)(nil), // 19: aggregator.v1.PublicInputs + (*InputProver)(nil), // 20: aggregator.v1.InputProver + (*PublicInputsExtended)(nil), // 21: aggregator.v1.PublicInputsExtended + nil, // 22: aggregator.v1.InputProver.DbEntry + nil, // 23: aggregator.v1.InputProver.ContractsBytecodeEntry +} +var file_aggregator_proto_depIdxs = []int32{ + 6, // 0: aggregator.v1.AggregatorMessage.get_status_request:type_name -> aggregator.v1.GetStatusRequest + 7, // 1: aggregator.v1.AggregatorMessage.gen_batch_proof_request:type_name -> aggregator.v1.GenBatchProofRequest + 8, // 2: aggregator.v1.AggregatorMessage.gen_aggregated_proof_request:type_name -> aggregator.v1.GenAggregatedProofRequest + 9, // 3: aggregator.v1.AggregatorMessage.gen_final_proof_request:type_name -> aggregator.v1.GenFinalProofRequest + 10, // 4: aggregator.v1.AggregatorMessage.cancel_request:type_name -> aggregator.v1.CancelRequest + 11, // 5: aggregator.v1.AggregatorMessage.get_proof_request:type_name -> aggregator.v1.GetProofRequest + 12, // 6: aggregator.v1.ProverMessage.get_status_response:type_name -> aggregator.v1.GetStatusResponse + 13, // 7: aggregator.v1.ProverMessage.gen_batch_proof_response:type_name -> aggregator.v1.GenBatchProofResponse + 14, // 8: aggregator.v1.ProverMessage.gen_aggregated_proof_response:type_name -> aggregator.v1.GenAggregatedProofResponse + 15, // 9: aggregator.v1.ProverMessage.gen_final_proof_response:type_name -> aggregator.v1.GenFinalProofResponse + 16, // 10: aggregator.v1.ProverMessage.cancel_response:type_name -> aggregator.v1.CancelResponse + 17, // 11: aggregator.v1.ProverMessage.get_proof_response:type_name -> aggregator.v1.GetProofResponse + 20, // 12: aggregator.v1.GenBatchProofRequest.input:type_name -> aggregator.v1.InputProver + 1, // 13: aggregator.v1.GetStatusResponse.status:type_name -> aggregator.v1.GetStatusResponse.Status + 0, // 14: aggregator.v1.GenBatchProofResponse.result:type_name -> aggregator.v1.Result + 0, // 15: aggregator.v1.GenAggregatedProofResponse.result:type_name -> aggregator.v1.Result + 0, // 16: aggregator.v1.GenFinalProofResponse.result:type_name -> aggregator.v1.Result + 0, // 17: aggregator.v1.CancelResponse.result:type_name -> aggregator.v1.Result + 18, // 18: aggregator.v1.GetProofResponse.final_proof:type_name -> aggregator.v1.FinalProof + 2, // 19: aggregator.v1.GetProofResponse.result:type_name -> aggregator.v1.GetProofResponse.Result + 21, // 20: aggregator.v1.FinalProof.public:type_name -> aggregator.v1.PublicInputsExtended + 19, // 21: aggregator.v1.InputProver.public_inputs:type_name -> aggregator.v1.PublicInputs + 22, // 22: aggregator.v1.InputProver.db:type_name -> aggregator.v1.InputProver.DbEntry + 23, // 23: aggregator.v1.InputProver.contracts_bytecode:type_name -> aggregator.v1.InputProver.ContractsBytecodeEntry + 19, // 24: aggregator.v1.PublicInputsExtended.public_inputs:type_name -> aggregator.v1.PublicInputs + 5, // 25: aggregator.v1.AggregatorService.Channel:input_type -> aggregator.v1.ProverMessage + 4, // 26: aggregator.v1.AggregatorService.Channel:output_type -> aggregator.v1.AggregatorMessage + 26, // [26:27] is the sub-list for method output_type + 25, // [25:26] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name +} + +func init() { file_aggregator_proto_init() } +func file_aggregator_proto_init() { + if File_aggregator_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_aggregator_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Version); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AggregatorMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProverMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetStatusRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenBatchProofRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenAggregatedProofRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenFinalProofRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CancelRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetProofRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetStatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenBatchProofResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenAggregatedProofResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenFinalProofResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CancelResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetProofResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FinalProof); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicInputs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InputProver); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_aggregator_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicInputsExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_aggregator_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*AggregatorMessage_GetStatusRequest)(nil), + (*AggregatorMessage_GenBatchProofRequest)(nil), + (*AggregatorMessage_GenAggregatedProofRequest)(nil), + (*AggregatorMessage_GenFinalProofRequest)(nil), + (*AggregatorMessage_CancelRequest)(nil), + (*AggregatorMessage_GetProofRequest)(nil), + } + file_aggregator_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ProverMessage_GetStatusResponse)(nil), + (*ProverMessage_GenBatchProofResponse)(nil), + (*ProverMessage_GenAggregatedProofResponse)(nil), + (*ProverMessage_GenFinalProofResponse)(nil), + (*ProverMessage_CancelResponse)(nil), + (*ProverMessage_GetProofResponse)(nil), + } + file_aggregator_proto_msgTypes[14].OneofWrappers = []interface{}{ + (*GetProofResponse_FinalProof)(nil), + (*GetProofResponse_RecursiveProof)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_aggregator_proto_rawDesc, + NumEnums: 3, + NumMessages: 21, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_aggregator_proto_goTypes, + DependencyIndexes: file_aggregator_proto_depIdxs, + EnumInfos: file_aggregator_proto_enumTypes, + MessageInfos: file_aggregator_proto_msgTypes, + }.Build() + File_aggregator_proto = out.File + file_aggregator_proto_rawDesc = nil + file_aggregator_proto_goTypes = nil + file_aggregator_proto_depIdxs = nil +} diff --git a/aggregator/pb/aggregator_grpc.pb.go b/aggregator/pb/aggregator_grpc.pb.go new file mode 100644 index 0000000000..8d2b33815d --- /dev/null +++ b/aggregator/pb/aggregator_grpc.pb.go @@ -0,0 +1,137 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: aggregator.proto + +package pb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// AggregatorServiceClient is the client API for AggregatorService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AggregatorServiceClient interface { + Channel(ctx context.Context, opts ...grpc.CallOption) (AggregatorService_ChannelClient, error) +} + +type aggregatorServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAggregatorServiceClient(cc grpc.ClientConnInterface) AggregatorServiceClient { + return &aggregatorServiceClient{cc} +} + +func (c *aggregatorServiceClient) Channel(ctx context.Context, opts ...grpc.CallOption) (AggregatorService_ChannelClient, error) { + stream, err := c.cc.NewStream(ctx, &AggregatorService_ServiceDesc.Streams[0], "/aggregator.v1.AggregatorService/Channel", opts...) + if err != nil { + return nil, err + } + x := &aggregatorServiceChannelClient{stream} + return x, nil +} + +type AggregatorService_ChannelClient interface { + Send(*ProverMessage) error + Recv() (*AggregatorMessage, error) + grpc.ClientStream +} + +type aggregatorServiceChannelClient struct { + grpc.ClientStream +} + +func (x *aggregatorServiceChannelClient) Send(m *ProverMessage) error { + return x.ClientStream.SendMsg(m) +} + +func (x *aggregatorServiceChannelClient) Recv() (*AggregatorMessage, error) { + m := new(AggregatorMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// AggregatorServiceServer is the server API for AggregatorService service. +// All implementations must embed UnimplementedAggregatorServiceServer +// for forward compatibility +type AggregatorServiceServer interface { + Channel(AggregatorService_ChannelServer) error + mustEmbedUnimplementedAggregatorServiceServer() +} + +// UnimplementedAggregatorServiceServer must be embedded to have forward compatible implementations. +type UnimplementedAggregatorServiceServer struct { +} + +func (UnimplementedAggregatorServiceServer) Channel(AggregatorService_ChannelServer) error { + return status.Errorf(codes.Unimplemented, "method Channel not implemented") +} +func (UnimplementedAggregatorServiceServer) mustEmbedUnimplementedAggregatorServiceServer() {} + +// UnsafeAggregatorServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AggregatorServiceServer will +// result in compilation errors. +type UnsafeAggregatorServiceServer interface { + mustEmbedUnimplementedAggregatorServiceServer() +} + +func RegisterAggregatorServiceServer(s grpc.ServiceRegistrar, srv AggregatorServiceServer) { + s.RegisterService(&AggregatorService_ServiceDesc, srv) +} + +func _AggregatorService_Channel_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(AggregatorServiceServer).Channel(&aggregatorServiceChannelServer{stream}) +} + +type AggregatorService_ChannelServer interface { + Send(*AggregatorMessage) error + Recv() (*ProverMessage, error) + grpc.ServerStream +} + +type aggregatorServiceChannelServer struct { + grpc.ServerStream +} + +func (x *aggregatorServiceChannelServer) Send(m *AggregatorMessage) error { + return x.ServerStream.SendMsg(m) +} + +func (x *aggregatorServiceChannelServer) Recv() (*ProverMessage, error) { + m := new(ProverMessage) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// AggregatorService_ServiceDesc is the grpc.ServiceDesc for AggregatorService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AggregatorService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "aggregator.v1.AggregatorService", + HandlerType: (*AggregatorServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "Channel", + Handler: _AggregatorService_Channel_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "aggregator.proto", +} diff --git a/aggregator/prover/client.go b/aggregator/prover/client.go deleted file mode 100644 index 2669b6bb56..0000000000 --- a/aggregator/prover/client.go +++ /dev/null @@ -1,109 +0,0 @@ -package prover - -import ( - "context" - "fmt" - "time" - - "github.com/0xPolygonHermez/zkevm-node/config/types" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" - "google.golang.org/grpc" -) - -// Client wrapper for the prover client -type Client struct { - Prover *Prover - IntervalFrequencyToGetProofGenerationState types.Duration -} - -// NewClient inits prover wrapper client -func NewClient(proverURI string, intervalFrequencyToGetProofGenerationState types.Duration) *Client { - return &Client{ - Prover: NewProver(proverURI), - IntervalFrequencyToGetProofGenerationState: intervalFrequencyToGetProofGenerationState, - } -} - -// GetURI return the URI of the prover -func (c *Client) GetURI() string { - return c.Prover.URI -} - -// IsIdle indicates the prover is ready to process requests -func (c *Client) IsIdle(ctx context.Context) bool { - var opts []grpc.CallOption - status, err := c.Prover.Client.GetStatus(ctx, &pb.GetStatusRequest{}, opts...) - if err != nil || status.State != pb.GetStatusResponse_STATUS_PROVER_IDLE { - return false - } - return true -} - -// GetGenProofID get id of generation proof request -func (c *Client) GetGenProofID(ctx context.Context, inputProver *pb.InputProver) (string, error) { - genProofRequest := pb.GenProofRequest{Input: inputProver} - // init connection to the prover - var opts []grpc.CallOption - resGenProof, err := c.Prover.Client.GenProof(ctx, &genProofRequest, opts...) - if err != nil { - return "", fmt.Errorf("failed to connect to the prover to gen proof, err: %v", err) - } - - log.Debugf("Data sent to the prover: %+v", inputProver) - genProofRes := resGenProof.GetResult() - if genProofRes != pb.GenProofResponse_RESULT_GEN_PROOF_OK { - return "", fmt.Errorf("failed to get result from the prover, batchNumber: %d, err: %v", inputProver.PublicInputs.BatchNum, err) - } - genProofID := resGenProof.GetId() - - return genProofID, err -} - -// GetResGetProof get result from proof generation -func (c *Client) GetResGetProof(ctx context.Context, genProofID string, batchNumber uint64) (*pb.GetProofResponse, error) { - resGetProof := &pb.GetProofResponse{Result: -1} - getProofCtx, getProofCtxCancel := context.WithCancel(ctx) - defer getProofCtxCancel() - getProofClient, err := c.Prover.Client.GetProof(getProofCtx) - if err != nil { - return nil, fmt.Errorf("failed to init getProofClient, batchNumber: %d, err: %v", batchNumber, err) - } - for resGetProof.Result != pb.GetProofResponse_RESULT_GET_PROOF_COMPLETED_OK { - err = getProofClient.Send(&pb.GetProofRequest{ - Id: genProofID, - }) - if err != nil { - return nil, fmt.Errorf("failed to send get proof request to the prover, batchNumber: %d, err: %v", batchNumber, err) - } - - resGetProof, err = getProofClient.Recv() - if err != nil { - return nil, fmt.Errorf("failed to get proof from the prover, batchNumber: %d, err: %v", batchNumber, err) - } - - resGetProofState := resGetProof.GetResult() - if resGetProofState == pb.GetProofResponse_RESULT_GET_PROOF_ERROR || - resGetProofState == pb.GetProofResponse_RESULT_GET_PROOF_COMPLETED_ERROR { - log.Fatalf("failed to get a proof for batch, batch number %d", batchNumber) - } - if resGetProofState == pb.GetProofResponse_RESULT_GET_PROOF_INTERNAL_ERROR { - return nil, fmt.Errorf("failed to generate proof for batch, batchNumber: %v, ResGetProofState: %v", batchNumber, resGetProofState) - } - - if resGetProofState == pb.GetProofResponse_RESULT_GET_PROOF_CANCEL { - log.Warnf("proof generation was cancelled, batchNumber: %v", batchNumber) - break - } - - if resGetProofState == pb.GetProofResponse_RESULT_GET_PROOF_PENDING { - // in this case aggregator will wait, to send another request - time.Sleep(c.IntervalFrequencyToGetProofGenerationState.Duration) - } - } - - // getProofCtxCancel call closes the connection stream with the prover. This is the only way to close it by client - getProofCtxCancel() - - return resGetProof, nil -} diff --git a/aggregator/prover/prover.go b/aggregator/prover/prover.go index d9fd324d7f..2a61a1678d 100644 --- a/aggregator/prover/prover.go +++ b/aggregator/prover/prover.go @@ -2,81 +2,336 @@ package prover import ( "context" + "errors" + "fmt" + "net" "time" + "github.com/0xPolygonHermez/zkevm-node/aggregator/metrics" + "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" + "github.com/0xPolygonHermez/zkevm-node/config/types" "github.com/0xPolygonHermez/zkevm-node/log" - proverclientpb "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" - "google.golang.org/grpc" - "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/credentials/insecure" ) -// Prover struct +var ( + ErrBadProverResponse = errors.New("Prover returned wrong type for response") //nolint:revive + ErrProverInternalError = errors.New("Prover returned INTERNAL_ERROR response") //nolint:revive + ErrProverCompletedError = errors.New("Prover returned COMPLETED_ERROR response") //nolint:revive + ErrBadRequest = errors.New("Prover returned ERROR for a bad request") //nolint:revive + ErrUnspecified = errors.New("Prover returned an UNSPECIFIED response") //nolint:revive + ErrUnknown = errors.New("Prover returned an unknown response") //nolint:revive + ErrProofCanceled = errors.New("Proof has been canceled") //nolint:revive +) + +// Prover abstraction of the grpc prover client. type Prover struct { - URI string - Client proverclientpb.ZKProverServiceClient - Conn *grpc.ClientConn + name string + id string + address net.Addr + proofStatePollingInterval types.Duration + stream pb.AggregatorService_ChannelServer } -// NewProver creates a new Prover -func NewProver(proverURI string) *Prover { - const checkWaitInSeconds = 20 - ctx := context.Background() - tickerCheckConnection := time.NewTicker(checkWaitInSeconds * time.Second) - opts := []grpc.DialOption{ - // TODO: once we have user and password for prover server, change this - grpc.WithTransportCredentials(insecure.NewCredentials()), +// New returns a new Prover instance. +func New(stream pb.AggregatorService_ChannelServer, addr net.Addr, proofStatePollingInterval types.Duration) (*Prover, error) { + p := &Prover{ + stream: stream, + address: addr, + proofStatePollingInterval: proofStatePollingInterval, } - proverConn, err := grpc.Dial(proverURI, opts...) + status, err := p.Status() if err != nil { - log.Fatalf("fail to dial: %v", err) + return nil, fmt.Errorf("Failed to retrieve prover id %w", err) + } + p.name = status.ProverName + p.id = status.ProverId + return p, nil +} + +// Name returns the Prover name. +func (p *Prover) Name() string { return p.name } + +// ID returns the Prover ID. +func (p *Prover) ID() string { return p.id } + +// Addr returns the prover IP address. +func (p *Prover) Addr() string { + if p.address == nil { + return "" } + return p.address.String() +} - proverClient := proverclientpb.NewZKProverServiceClient(proverConn) - prover := &Prover{URI: proverURI, Client: proverClient, Conn: proverConn} +// Status gets the prover status. +func (p *Prover) Status() (*pb.GetStatusResponse, error) { + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_GetStatusRequest{ + GetStatusRequest: &pb.GetStatusRequest{}, + }, + } + res, err := p.call(req) + if err != nil { + return nil, err + } + if msg, ok := res.Response.(*pb.ProverMessage_GetStatusResponse); ok { + return msg.GetStatusResponse, nil + } + return nil, fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_GetStatusResponse{}, res.Response) +} - go func() { - waitTick(ctx, tickerCheckConnection) - for { - prover.checkConnection(ctx, tickerCheckConnection) +// IsIdle returns true if the prover is idling. +func (p *Prover) IsIdle() (bool, error) { + status, err := p.Status() + if err != nil { + return false, err + } + return status.Status == pb.GetStatusResponse_STATUS_IDLE, nil +} + +// SupportsForkID returns true if the prover supports the given fork id. +func (p *Prover) SupportsForkID(forkID uint64) bool { + status, err := p.Status() + if err != nil { + log.Warnf("Error asking status for prover ID %s: %v", p.ID(), err) + return false + } + + log.Debugf("Prover %s supports fork ID %d", p.ID(), status.ForkId) + + return status.ForkId == forkID +} + +// BatchProof instructs the prover to generate a batch proof for the provided +// input. It returns the ID of the proof being computed. +func (p *Prover) BatchProof(input *pb.InputProver) (*string, error) { + metrics.WorkingProver() + + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_GenBatchProofRequest{ + GenBatchProofRequest: &pb.GenBatchProofRequest{Input: input}, + }, + } + res, err := p.call(req) + if err != nil { + return nil, err + } + + if msg, ok := res.Response.(*pb.ProverMessage_GenBatchProofResponse); ok { + switch msg.GenBatchProofResponse.Result { + case pb.Result_RESULT_UNSPECIFIED: + return nil, fmt.Errorf("failed to generate proof %s, %w, input %v", msg.GenBatchProofResponse.String(), ErrUnspecified, input) + case pb.Result_RESULT_OK: + return &msg.GenBatchProofResponse.Id, nil + case pb.Result_RESULT_ERROR: + return nil, fmt.Errorf("failed to generate proof %s, %w, input %v", msg.GenBatchProofResponse.String(), ErrBadRequest, input) + case pb.Result_RESULT_INTERNAL_ERROR: + return nil, fmt.Errorf("failed to generate proof %s, %w, input %v", msg.GenBatchProofResponse.String(), ErrProverInternalError, input) + default: + return nil, fmt.Errorf("failed to generate proof %s, %w,input %v", msg.GenBatchProofResponse.String(), ErrUnknown, input) } - }() + } - return prover + return nil, fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_GenBatchProofResponse{}, res.Response) } -func (p *Prover) checkConnection(ctx context.Context, ticker *time.Ticker) { - state := p.Conn.GetState() - log.Debugf("Checking connection to prover %v. State: %v", p.URI, state) +// AggregatedProof instructs the prover to generate an aggregated proof from +// the two inputs provided. It returns the ID of the proof being computed. +func (p *Prover) AggregatedProof(inputProof1, inputProof2 string) (*string, error) { + metrics.WorkingProver() + + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_GenAggregatedProofRequest{ + GenAggregatedProofRequest: &pb.GenAggregatedProofRequest{ + RecursiveProof_1: inputProof1, + RecursiveProof_2: inputProof2, + }, + }, + } + res, err := p.call(req) + if err != nil { + return nil, err + } - if state != connectivity.Ready { - log.Infof("Connection to prover %v seems broken. Trying to reconnect...", p.URI) - if err := p.Conn.Close(); err != nil { - log.Errorf("Could not properly close gRPC connection: %v", err) + if msg, ok := res.Response.(*pb.ProverMessage_GenAggregatedProofResponse); ok { + switch msg.GenAggregatedProofResponse.Result { + case pb.Result_RESULT_UNSPECIFIED: + return nil, fmt.Errorf("failed to aggregate proofs %s, %w, input 1 %s, input 2 %s", + msg.GenAggregatedProofResponse.String(), ErrUnspecified, inputProof1, inputProof2) + case pb.Result_RESULT_OK: + return &msg.GenAggregatedProofResponse.Id, nil + case pb.Result_RESULT_ERROR: + return nil, fmt.Errorf("failed to aggregate proofs %s, %w, input 1 %s, input 2 %s", + msg.GenAggregatedProofResponse.String(), ErrBadRequest, inputProof1, inputProof2) + case pb.Result_RESULT_INTERNAL_ERROR: + return nil, fmt.Errorf("failed to aggregate proofs %s, %w, input 1 %s, input 2 %s", + msg.GenAggregatedProofResponse.String(), ErrProverInternalError, inputProof1, inputProof2) + default: + return nil, fmt.Errorf("failed to aggregate proofs %s, %w, input 1 %s, input 2 %s", + msg.GenAggregatedProofResponse.String(), ErrUnknown, inputProof1, inputProof2) } + } + + return nil, fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_GenAggregatedProofResponse{}, res.Response) +} + +// FinalProof instructs the prover to generate a final proof for the given +// input. It returns the ID of the proof being computed. +func (p *Prover) FinalProof(inputProof string, aggregatorAddr string) (*string, error) { + metrics.WorkingProver() + + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_GenFinalProofRequest{ + GenFinalProofRequest: &pb.GenFinalProofRequest{ + RecursiveProof: inputProof, + AggregatorAddr: aggregatorAddr, + }, + }, + } + res, err := p.call(req) + if err != nil { + return nil, err + } - opts := []grpc.DialOption{ - // TODO: once we have user and password for prover server, change this - grpc.WithTransportCredentials(insecure.NewCredentials()), + if msg, ok := res.Response.(*pb.ProverMessage_GenFinalProofResponse); ok { + switch msg.GenFinalProofResponse.Result { + case pb.Result_RESULT_UNSPECIFIED: + return nil, fmt.Errorf("failed to generate final proof %s, %w, input %s", + msg.GenFinalProofResponse.String(), ErrUnspecified, inputProof) + case pb.Result_RESULT_OK: + return &msg.GenFinalProofResponse.Id, nil + case pb.Result_RESULT_ERROR: + return nil, fmt.Errorf("failed to generate final proof %s, %w, input %s", + msg.GenFinalProofResponse.String(), ErrBadRequest, inputProof) + case pb.Result_RESULT_INTERNAL_ERROR: + return nil, fmt.Errorf("failed to generate final proof %s, %w, input %s", + msg.GenFinalProofResponse.String(), ErrProverInternalError, inputProof) + default: + return nil, fmt.Errorf("failed to generate final proof %s, %w, input %s", + msg.GenFinalProofResponse.String(), ErrUnknown, inputProof) } - proverConn, err := grpc.Dial(p.URI, opts...) - if err != nil { - log.Errorf("Could not reconnect to: %v: %v", p.URI, err) - waitTick(ctx, ticker) + } + return nil, fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_GenFinalProofResponse{}, res.Response) +} + +// CancelProofRequest asks the prover to stop the generation of the proof +// matching the provided proofID. +func (p *Prover) CancelProofRequest(proofID string) error { + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_CancelRequest{ + CancelRequest: &pb.CancelRequest{Id: proofID}, + }, + } + res, err := p.call(req) + if err != nil { + return err + } + if msg, ok := res.Response.(*pb.ProverMessage_CancelResponse); ok { + switch msg.CancelResponse.Result { + case pb.Result_RESULT_UNSPECIFIED: + return fmt.Errorf("failed to cancel proof id [%s], %w, %s", + proofID, ErrUnspecified, msg.CancelResponse.String()) + case pb.Result_RESULT_OK: + return nil + case pb.Result_RESULT_ERROR: + return fmt.Errorf("failed to cancel proof id [%s], %w, %s", + proofID, ErrBadRequest, msg.CancelResponse.String()) + case pb.Result_RESULT_INTERNAL_ERROR: + return fmt.Errorf("failed to cancel proof id [%s], %w, %s", + proofID, ErrProverInternalError, msg.CancelResponse.String()) + default: + return fmt.Errorf("failed to cancel proof id [%s], %w, %s", + proofID, ErrUnknown, msg.CancelResponse.String()) } + } + return fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_CancelResponse{}, res.Response) +} - p.Client = proverclientpb.NewZKProverServiceClient(proverConn) - p.Conn = proverConn +// WaitRecursiveProof waits for a recursive proof to be generated by the prover +// and returns it. +func (p *Prover) WaitRecursiveProof(ctx context.Context, proofID string) (string, error) { + res, err := p.waitProof(ctx, proofID) + if err != nil { + return "", err } + resProof := res.Proof.(*pb.GetProofResponse_RecursiveProof) + return resProof.RecursiveProof, nil +} - waitTick(ctx, ticker) +// WaitFinalProof waits for the final proof to be generated by the prover and +// returns it. +func (p *Prover) WaitFinalProof(ctx context.Context, proofID string) (*pb.FinalProof, error) { + res, err := p.waitProof(ctx, proofID) + if err != nil { + return nil, err + } + resProof := res.Proof.(*pb.GetProofResponse_FinalProof) + return resProof.FinalProof, nil } -func waitTick(ctx context.Context, ticker *time.Ticker) { - select { - case <-ticker.C: - // nothing - case <-ctx.Done(): - return +// waitProof waits for a proof to be generated by the prover and returns the +// prover response. +func (p *Prover) waitProof(ctx context.Context, proofID string) (*pb.GetProofResponse, error) { + defer metrics.IdlingProver() + + req := &pb.AggregatorMessage{ + Request: &pb.AggregatorMessage_GetProofRequest{ + GetProofRequest: &pb.GetProofRequest{ + // TODO(pg): set Timeout field? + Id: proofID, + }, + }, + } + + for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + res, err := p.call(req) + if err != nil { + return nil, err + } + if msg, ok := res.Response.(*pb.ProverMessage_GetProofResponse); ok { + switch msg.GetProofResponse.Result { + case pb.GetProofResponse_RESULT_PENDING: + time.Sleep(p.proofStatePollingInterval.Duration) + continue + case pb.GetProofResponse_RESULT_UNSPECIFIED: + return nil, fmt.Errorf("failed to get proof ID: %s, %w, prover response: %s", + proofID, ErrUnspecified, msg.GetProofResponse.String()) + case pb.GetProofResponse_RESULT_COMPLETED_OK: + return msg.GetProofResponse, nil + case pb.GetProofResponse_RESULT_ERROR: + return nil, fmt.Errorf("failed to get proof with ID %s, %w, prover response: %s", + proofID, ErrBadRequest, msg.GetProofResponse.String()) + case pb.GetProofResponse_RESULT_COMPLETED_ERROR: + return nil, fmt.Errorf("failed to get proof with ID %s, %w, prover response: %s", + proofID, ErrProverCompletedError, msg.GetProofResponse.String()) + case pb.GetProofResponse_RESULT_INTERNAL_ERROR: + return nil, fmt.Errorf("failed to get proof ID: %s, %w, prover response: %s", + proofID, ErrProverInternalError, msg.GetProofResponse.String()) + case pb.GetProofResponse_RESULT_CANCEL: + return nil, fmt.Errorf("proof generation was cancelled for proof ID %s, %w, prover response: %s", + proofID, ErrProofCanceled, msg.GetProofResponse.String()) + default: + return nil, fmt.Errorf("failed to get proof ID: %s, %w, prover response: %s", + proofID, ErrUnknown, msg.GetProofResponse.String()) + } + } + return nil, fmt.Errorf("%w, wanted %T, got %T", ErrBadProverResponse, &pb.ProverMessage_GetProofResponse{}, res.Response) + } + } +} + +// call sends a message to the prover and waits to receive the response over +// the connection stream. +func (p *Prover) call(req *pb.AggregatorMessage) (*pb.ProverMessage, error) { + if err := p.stream.Send(req); err != nil { + return nil, err + } + res, err := p.stream.Recv() + if err != nil { + return nil, err } + return res, nil } diff --git a/ci/e2e-group1/constants.go b/ci/e2e-group1/constants.go new file mode 100644 index 0000000000..b3bc85cbc0 --- /dev/null +++ b/ci/e2e-group1/constants.go @@ -0,0 +1,13 @@ +package e2e + +// import "github.com/ethereum/go-ethereum/common" + +// const ( +// toAddressHex = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +// nTxs = 10 +// gerFinalityBlocks = uint64(1) +// ) + +// var ( +// toAddress = common.HexToAddress(toAddressHex) +// ) diff --git a/ci/e2e-group2/ethtransfer_test.go b/ci/e2e-group1/ethtransfer_test.go similarity index 100% rename from ci/e2e-group2/ethtransfer_test.go rename to ci/e2e-group1/ethtransfer_test.go diff --git a/ci/e2e-group1/preEIP155_test.go b/ci/e2e-group1/preEIP155_test.go new file mode 120000 index 0000000000..3893978046 --- /dev/null +++ b/ci/e2e-group1/preEIP155_test.go @@ -0,0 +1 @@ +../../test/e2e/preEIP155_test.go \ No newline at end of file diff --git a/ci/e2e-group1/shared.go b/ci/e2e-group1/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group1/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group1/state_test.go b/ci/e2e-group1/state_test.go deleted file mode 120000 index b736bd68f4..0000000000 --- a/ci/e2e-group1/state_test.go +++ /dev/null @@ -1 +0,0 @@ -../../test/e2e/state_test.go \ No newline at end of file diff --git a/ci/e2e-group2/broadcast_test.go b/ci/e2e-group2/broadcast_test.go deleted file mode 120000 index 404a0d32e5..0000000000 --- a/ci/e2e-group2/broadcast_test.go +++ /dev/null @@ -1 +0,0 @@ -../../test/e2e/broadcast_test.go \ No newline at end of file diff --git a/ci/e2e-group2/sc_test.go b/ci/e2e-group3/sc_test.go similarity index 100% rename from ci/e2e-group2/sc_test.go rename to ci/e2e-group3/sc_test.go diff --git a/ci/e2e-group3/shared.go b/ci/e2e-group3/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group3/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group3/uniswap_test.go b/ci/e2e-group3/uniswap_test.go deleted file mode 120000 index d4c236e411..0000000000 --- a/ci/e2e-group3/uniswap_test.go +++ /dev/null @@ -1 +0,0 @@ -../../test/e2e/uniswap_test.go \ No newline at end of file diff --git a/ci/e2e-group4/jsonrpc1_test.go b/ci/e2e-group4/jsonrpc1_test.go new file mode 120000 index 0000000000..572c7a9697 --- /dev/null +++ b/ci/e2e-group4/jsonrpc1_test.go @@ -0,0 +1 @@ +../../test/e2e/jsonrpc1_test.go \ No newline at end of file diff --git a/ci/e2e-group4/shared.go b/ci/e2e-group4/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group4/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group5/debug_shared.go b/ci/e2e-group5/debug_shared.go new file mode 120000 index 0000000000..8dd0ba0e4a --- /dev/null +++ b/ci/e2e-group5/debug_shared.go @@ -0,0 +1 @@ +../../test/e2e/debug_shared.go \ No newline at end of file diff --git a/ci/e2e-group5/debug_test.go b/ci/e2e-group5/debug_test.go new file mode 120000 index 0000000000..59afb4b681 --- /dev/null +++ b/ci/e2e-group5/debug_test.go @@ -0,0 +1 @@ +../../test/e2e/debug_test.go \ No newline at end of file diff --git a/ci/e2e-group5/shared.go b/ci/e2e-group5/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group5/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group6/permissionlessrpc_test.go b/ci/e2e-group6/permissionlessrpc_test.go new file mode 120000 index 0000000000..2534ae8604 --- /dev/null +++ b/ci/e2e-group6/permissionlessrpc_test.go @@ -0,0 +1 @@ +../../test/e2e/permissionlessrpc_test.go \ No newline at end of file diff --git a/ci/e2e-group7/jsonrpc2_test.go b/ci/e2e-group7/jsonrpc2_test.go new file mode 120000 index 0000000000..f38feba15f --- /dev/null +++ b/ci/e2e-group7/jsonrpc2_test.go @@ -0,0 +1 @@ +../../test/e2e/jsonrpc2_test.go \ No newline at end of file diff --git a/ci/e2e-group7/shared.go b/ci/e2e-group7/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group7/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group8/debug_calltracer_test.go b/ci/e2e-group8/debug_calltracer_test.go new file mode 120000 index 0000000000..3189bf3b11 --- /dev/null +++ b/ci/e2e-group8/debug_calltracer_test.go @@ -0,0 +1 @@ +../../test/e2e/debug_calltracer_test.go \ No newline at end of file diff --git a/ci/e2e-group8/debug_shared.go b/ci/e2e-group8/debug_shared.go new file mode 120000 index 0000000000..8dd0ba0e4a --- /dev/null +++ b/ci/e2e-group8/debug_shared.go @@ -0,0 +1 @@ +../../test/e2e/debug_shared.go \ No newline at end of file diff --git a/ci/e2e-group8/shared.go b/ci/e2e-group8/shared.go new file mode 120000 index 0000000000..2762ace935 --- /dev/null +++ b/ci/e2e-group8/shared.go @@ -0,0 +1 @@ +../../test/e2e/shared.go \ No newline at end of file diff --git a/ci/e2e-group9/forced_batches_test.go b/ci/e2e-group9/forced_batches_test.go new file mode 100644 index 0000000000..b4455bfc89 --- /dev/null +++ b/ci/e2e-group9/forced_batches_test.go @@ -0,0 +1,225 @@ +package e2e + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmglobalexitroot" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/constants" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestForcedBatches(t *testing.T) { + if testing.Short() { + t.Skip() + } + + defer func() { + require.NoError(t, operations.Teardown()) + }() + + var err error + nTxs := 10 + ctx := context.Background() + opsman, auth, client, amount, gasLimit, gasPrice, nonce := setupEnvironment(ctx, t) + + txs := make([]*types.Transaction, 0, nTxs) + for i := 0; i < nTxs; i++ { + tx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) + nonce = nonce + 1 + txs = append(txs, tx) + } + + var l2BlockNumbers []*big.Int + l2BlockNumbers, err = operations.ApplyL2Txs(ctx, txs, auth, client, operations.VerifiedConfirmationLevel) + require.NoError(t, err) + + time.Sleep(2 * time.Second) + amount = big.NewInt(0).Add(amount, big.NewInt(10)) + unsignedTx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) + signedTx, err := auth.Signer(auth.From, unsignedTx) + require.NoError(t, err) + encodedTxs, err := state.EncodeTransactions([]types.Transaction{*signedTx}) + require.NoError(t, err) + forcedBatch, err := sendForcedBatch(t, encodedTxs, opsman) + require.NoError(t, err) + + // Checking if all txs sent before the forced batch were processed within previous closed batch + for _, l2blockNum := range l2BlockNumbers { + batch, err := opsman.State().GetBatchByL2BlockNumber(ctx, l2blockNum.Uint64(), nil) + require.NoError(t, err) + require.Less(t, batch.BatchNumber, forcedBatch.BatchNumber) + } +} + +func setupEnvironment(ctx context.Context, t *testing.T) (*operations.Manager, *bind.TransactOpts, *ethclient.Client, *big.Int, uint64, *big.Int, uint64) { + + err := operations.Teardown() + require.NoError(t, err) + opsCfg := operations.GetDefaultOperationsConfig() + opsCfg.State.MaxCumulativeGasUsed = 80000000000 + opsman, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsman.Setup() + require.NoError(t, err) + time.Sleep(5 * time.Second) + // Load account with balance on local genesis + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) + require.NoError(t, err) + // Load eth client + client, err := ethclient.Dial(operations.DefaultL2NetworkURL) + require.NoError(t, err) + // Send txs + amount := big.NewInt(10000) + senderBalance, err := client.BalanceAt(ctx, auth.From, nil) + require.NoError(t, err) + senderNonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + log.Infof("Receiver Addr: %v", toAddress.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", senderNonce) + + gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &toAddress, Value: amount}) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + return opsman, auth, client, amount, gasLimit, gasPrice, nonce +} + +func sendForcedBatch(t *testing.T, txs []byte, opsman *operations.Manager) (*state.Batch, error) { + ctx := context.Background() + st := opsman.State() + // Connect to ethereum node + ethClient, err := ethclient.Dial(operations.DefaultL1NetworkURL) + require.NoError(t, err) + + initialGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) + require.NoError(t, err) + + // Create smc client + zkEvmAddr := common.HexToAddress(operations.DefaultL1ZkEVMSmartContract) + zkEvm, err := polygonzkevm.NewPolygonzkevm(zkEvmAddr, ethClient) + require.NoError(t, err) + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + require.NoError(t, err) + + log.Info("Using address: ", auth.From) + + num, err := zkEvm.LastForceBatch(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + log.Info("Number of forceBatches in the smc: ", num) + + // Get tip + tip, err := zkEvm.GetForcedBatchFee(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + managerAddress, err := zkEvm.GlobalExitRootManager(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + manager, err := polygonzkevmglobalexitroot.NewPolygonzkevmglobalexitroot(managerAddress, ethClient) + require.NoError(t, err) + + rootInContract, err := manager.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + rootInContractHash := common.BytesToHash(rootInContract[:]) + + disallowed, err := zkEvm.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + if disallowed { + tx, err := zkEvm.ActivateForceBatches(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + // Send forceBatch + tx, err := zkEvm.ForceBatch(auth, txs, tip) + require.NoError(t, err) + + log.Info("TxHash: ", tx.Hash()) + time.Sleep(1 * time.Second) + + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + query := ethereum.FilterQuery{ + FromBlock: currentBlock.Number(), + Addresses: []common.Address{zkEvmAddr}, + } + logs, err := ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + + var forcedBatch *state.Batch + for _, vLog := range logs { + if vLog.Topics[0] != constants.ForcedBatchSignatureHash { + logs, err = ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + continue + } + fb, err := zkEvm.ParseForceBatch(vLog) + if err != nil { + log.Errorf("failed to parse force batch log event, err: ", err) + } + log.Debugf("log decoded: %+v", fb) + ger := fb.LastGlobalExitRoot + log.Info("GlobalExitRoot: ", ger) + log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) + fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) + return nil, err + } + log.Info("MinForcedTimestamp: ", fullBlock.Time()) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + for err == state.ErrStateNotSynchronized { + time.Sleep(1 * time.Second) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + } + log.Info("ForcedBatchNum: ", forcedBatch.BatchNumber) + require.NoError(t, err) + require.NotNil(t, forcedBatch) + + log.Info("Waiting for batch to be virtualized...") + err = operations.WaitBatchToBeVirtualized(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + log.Info("Waiting for batch to be consolidated...") + err = operations.WaitBatchToBeConsolidated(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + if rootInContractHash != initialGer.GlobalExitRoot { + finalGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) + require.NoError(t, err) + if finalGer.GlobalExitRoot != rootInContractHash { + log.Fatal("global exit root is not updated") + } + } + } + + return forcedBatch, nil +} diff --git a/ci/e2e-group9/forced_batches_vector_test.go b/ci/e2e-group9/forced_batches_vector_test.go new file mode 100644 index 0000000000..b4eb1d2a51 --- /dev/null +++ b/ci/e2e-group9/forced_batches_vector_test.go @@ -0,0 +1,228 @@ +package e2e + +import ( + "context" + "math/big" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/constants" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/vectors" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestForcedBatchesVectorFiles(t *testing.T) { + + if testing.Short() { + t.Skip() + } + vectorFilesDir := "./../vectors/src/state-transition/forced-tx" + ctx := context.Background() + err := filepath.Walk(vectorFilesDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && !strings.HasSuffix(info.Name(), "list.json") { + + t.Run(info.Name(), func(t *testing.T) { + + defer func() { + require.NoError(t, operations.Teardown()) + }() + + // Load test vectors + log.Info("=====================================================================") + log.Info(path) + log.Info("=====================================================================") + testCase, err := vectors.LoadStateTransitionTestCaseV2(path) + require.NoError(t, err) + + opsCfg := operations.GetDefaultOperationsConfig() + opsCfg.State.MaxCumulativeGasUsed = 80000000000 + opsman, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + + // Setting Genesis + log.Info("###################") + log.Info("# Setting Genesis #") + log.Info("###################") + genesisActions := vectors.GenerateGenesisActions(testCase.Genesis) + require.NoError(t, opsman.SetGenesis(genesisActions)) + require.NoError(t, opsman.Setup()) + + // Check initial root + log.Info("################################") + log.Info("# Verifying initial state root #") + log.Info("################################") + actualOldStateRoot, err := opsman.State().GetLastStateRoot(ctx, nil) + require.NoError(t, err) + require.Equal(t, testCase.ExpectedOldStateRoot, actualOldStateRoot.Hex()) + decodedData, err := hex.DecodeHex(testCase.BatchL2Data) + require.NoError(t, err) + _, txBytes, err := state.DecodeTxs(decodedData) + forcedBatch, err := sendForcedBatchForVector(t, txBytes, opsman) + require.NoError(t, err) + actualNewStateRoot := forcedBatch.StateRoot + isClosed, err := opsman.State().IsBatchClosed(ctx, forcedBatch.BatchNumber, nil) + require.NoError(t, err) + + // wait until is closed + for !isClosed { + time.Sleep(1 * time.Second) + isClosed, err = opsman.State().IsBatchClosed(ctx, forcedBatch.BatchNumber, nil) + require.NoError(t, err) + } + + log.Info("#######################") + log.Info("# Verifying new leafs #") + log.Info("#######################") + merkleTree := opsman.State().GetTree() + for _, expectedNewLeaf := range testCase.ExpectedNewLeafs { + if expectedNewLeaf.IsSmartContract { + log.Info("Smart Contract Address: ", expectedNewLeaf.Address) + } else { + log.Info("Account Address: ", expectedNewLeaf.Address) + } + log.Info("Verifying Balance...") + actualBalance, err := merkleTree.GetBalance(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.Balance.String(), actualBalance.String()) + + log.Info("Verifying Nonce...") + actualNonce, err := merkleTree.GetNonce(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.Nonce, actualNonce.String()) + if expectedNewLeaf.IsSmartContract { + log.Info("Verifying Storage...") + for positionHex, expectedNewStorageHex := range expectedNewLeaf.Storage { + position, ok := big.NewInt(0).SetString(positionHex[2:], 16) + require.True(t, ok) + expectedNewStorage, ok := big.NewInt(0).SetString(expectedNewStorageHex[2:], 16) + require.True(t, ok) + actualStorage, err := merkleTree.GetStorageAt(ctx, common.HexToAddress(expectedNewLeaf.Address), position, actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewStorage, actualStorage) + } + + log.Info("Verifying HashBytecode...") + actualHashByteCode, err := merkleTree.GetCodeHash(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.HashBytecode, common.BytesToHash(actualHashByteCode).String()) + } + } + return + }) + + return nil + } + return nil + }) + require.NoError(t, err) +} + +func sendForcedBatchForVector(t *testing.T, txs []byte, opsman *operations.Manager) (*state.Batch, error) { + ctx := context.Background() + st := opsman.State() + // Connect to ethereum node + ethClient, err := ethclient.Dial(operations.DefaultL1NetworkURL) + require.NoError(t, err) + + // Create smc client + zkEvmAddr := common.HexToAddress(operations.DefaultL1ZkEVMSmartContract) + zkEvm, err := polygonzkevm.NewPolygonzkevm(zkEvmAddr, ethClient) + require.NoError(t, err) + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + require.NoError(t, err) + + log.Info("Using address: ", auth.From) + num, err := zkEvm.LastForceBatch(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + log.Info("Number of forceBatches in the smc: ", num) + + // Get tip + tip, err := zkEvm.GetForcedBatchFee(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + disallowed, err := zkEvm.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + if disallowed { + tx, err := zkEvm.ActivateForceBatches(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + // Send forceBatch + tx, err := zkEvm.ForceBatch(auth, txs, tip) + require.NoError(t, err) + + log.Info("Forced Batch Submit to L1 TxHash: ", tx.Hash()) + time.Sleep(1 * time.Second) + + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + query := ethereum.FilterQuery{ + FromBlock: currentBlock.Number(), + Addresses: []common.Address{zkEvmAddr}, + } + logs, err := ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + + var forcedBatch *state.Batch + for _, vLog := range logs { + if vLog.Topics[0] != constants.ForcedBatchSignatureHash { + logs, err = ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + continue + } + fb, err := zkEvm.ParseForceBatch(vLog) + if err != nil { + log.Errorf("failed to parse force batch log event, err: ", err) + } + log.Debugf("log decoded: %+v", fb) + ger := fb.LastGlobalExitRoot + log.Info("GlobalExitRoot: ", ger) + log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) + fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) + return nil, err + } + log.Info("MinForcedTimestamp: ", fullBlock.Time()) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + for err == state.ErrStateNotSynchronized { + time.Sleep(1 * time.Second) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + } + require.NoError(t, err) + require.NotNil(t, forcedBatch) + + log.Info("Waiting Forced Batch to be virtualized ...") + err = operations.WaitBatchToBeVirtualized(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + log.Info("Waiting Forced Batch to be consolidated ...") + err = operations.WaitBatchToBeConsolidated(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + } + + return forcedBatch, nil +} diff --git a/ci/e2e-group9/shared.go b/ci/e2e-group9/shared.go new file mode 100644 index 0000000000..eb4fd66e7b --- /dev/null +++ b/ci/e2e-group9/shared.go @@ -0,0 +1,12 @@ +package e2e + +import "github.com/ethereum/go-ethereum/common" + +const ( + toAddressHex = "0x4d5Cf5032B2a844602278b01199ED191A86c93ff" + gerFinalityBlocks = uint64(250) +) + +var ( + toAddress = common.HexToAddress(toAddressHex) +) diff --git a/cmd/approve.go b/cmd/approve.go index da6032499a..d6d334e052 100644 --- a/cmd/approve.go +++ b/cmd/approve.go @@ -6,25 +6,38 @@ import ( "strings" "github.com/0xPolygonHermez/zkevm-node/config" + "github.com/0xPolygonHermez/zkevm-node/encoding" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v2" ) func approveTokens(ctx *cli.Context) error { - a := ctx.String(config.FlagAmount) - amount, _ := new(big.Float).SetString(a) - if amount == nil { - fmt.Println("Please, introduce a valid amount. Use '.' instead of ',' if it is a decimal number") - return nil + const bitSize uint = 256 + useMaxAmountArg := ctx.Bool(config.FlagMaxAmount) + var amount *big.Int + if !useMaxAmountArg { + amountArg := ctx.String(config.FlagAmount) + amount, _ = new(big.Int).SetString(amountArg, encoding.Base10) + if amount == nil { + fmt.Println("Please, introduce a valid amount in wei") + return nil + } + } else { + amount = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, bitSize), common.Big1) } + + addrKeyStorePath := ctx.String(config.FlagKeyStorePath) + addrPassword := ctx.String(config.FlagPassword) + c, err := config.Load(ctx) if err != nil { return err } if !ctx.Bool(config.FlagYes) { - fmt.Print("*WARNING* Are you sure you want to approve ", amount, - " tokens to be spent by the smc ? [y/N]: ") + fmt.Print("*WARNING* Are you sure you want to approve ", amount.String(), + " tokens (in wei) for the smc ? [y/N]: ") var input string if _, err := fmt.Scanln(&input); err != nil { return err @@ -37,10 +50,6 @@ func approveTokens(ctx *cli.Context) error { setupLog(c.Log) - runStateMigrations(c.StateDB) - runPoolMigrations(c.PoolDB) - runRPCMigrations(c.RPC.DB) - // Check if it is already registered etherman, err := newEtherman(*c) if err != nil { @@ -48,11 +57,14 @@ func approveTokens(ctx *cli.Context) error { return err } - const decimals = 1000000000000000000 - amountInWei := new(big.Float).Mul(amount, big.NewFloat(decimals)) - amountB := new(big.Int) - amountInWei.Int(amountB) - tx, err := etherman.ApproveMatic(amountB, c.NetworkConfig.PoEAddr) + // load auth from keystore file + auth, err := etherman.LoadAuthFromKeyStore(addrKeyStorePath, addrPassword) + if err != nil { + log.Fatal(err) + return err + } + + tx, err := etherman.ApproveMatic(ctx.Context, auth.From, amount, c.NetworkConfig.L1Config.ZkEVMAddr) if err != nil { return err } @@ -60,14 +72,19 @@ func approveTokens(ctx *cli.Context) error { mainnet = 1 rinkeby = 4 goerli = 5 + local = 1337 ) - switch c.NetworkConfig.L1ChainID { + switch c.NetworkConfig.L1Config.L1ChainID { case mainnet: fmt.Println("Check tx status: https://etherscan.io/tx/" + tx.Hash().String()) case rinkeby: fmt.Println("Check tx status: https://rinkeby.etherscan.io/tx/" + tx.Hash().String()) case goerli: fmt.Println("Check tx status: https://goerli.etherscan.io/tx/" + tx.Hash().String()) + case local: + fmt.Println("Local network. Tx Hash: " + tx.Hash().String()) + default: + fmt.Println("Unknown network. Tx Hash: " + tx.Hash().String()) } return nil } diff --git a/cmd/dumpstate.go b/cmd/dumpstate.go index 15026caf2b..2ca9855fc6 100644 --- a/cmd/dumpstate.go +++ b/cmd/dumpstate.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "os" "strings" "github.com/0xPolygonHermez/zkevm-node/config" @@ -34,9 +34,6 @@ var dumpStateFlags = []cli.Flag{ Required: true, }, &configFileFlag, - &networkFlag, - &customNetworkFlag, - &baseNetworkFlag, } type dumpedState struct { @@ -48,7 +45,7 @@ type dumpedState struct { type genesis state.Genesis func (g genesis) MarshalJSON() ([]byte, error) { - for _, action := range g.Actions { + for _, action := range g.GenesisActions { if !strings.HasPrefix(action.Value, "0x") { action.Value = fmt.Sprintf("0x%s", action.Value) } @@ -67,7 +64,7 @@ func (g genesis) MarshalJSON() ([]byte, error) { Actions []*state.GenesisAction }{ Alias: (Alias)(g), - Actions: g.Actions, + Actions: g.GenesisActions, }) } @@ -107,7 +104,7 @@ func dumpState(ctx *cli.Context) error { description := ctx.String(dumpStateFlagDescription) outputFile := ctx.String(dumpStateFlagOutput) if !strings.Contains(outputFile, ".json") { - return errors.New("Output file must end in .json") + return errors.New("output file must end in .json") } // Connect to SQL @@ -161,5 +158,5 @@ func dumpState(ctx *cli.Context) error { if err != nil { return err } - return ioutil.WriteFile(outputFile, file, 0600) //nolint:gomnd + return os.WriteFile(outputFile, file, 0600) //nolint:gomnd } diff --git a/cmd/main.go b/cmd/main.go index 22659cdb6b..75c5e55c19 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,34 +4,30 @@ import ( "fmt" "os" + "github.com/0xPolygonHermez/zkevm-node" "github.com/0xPolygonHermez/zkevm-node/config" "github.com/0xPolygonHermez/zkevm-node/jsonrpc" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/urfave/cli/v2" ) -const ( - // App name - appName = "zkevm-node" - // version represents the program based on the git tag - version = "v0.1.0" - // commit represents the program based on the git commit - commit = "dev" - // date represents the date of application was built - date = "" -) +const appName = "zkevm-node" const ( - // AGGREGATOR is the aggregator component identifier. + // AGGREGATOR is the aggregator component identifier AGGREGATOR = "aggregator" - // SEQUENCER is the sequencer component identifier. + // SEQUENCER is the sequencer component identifier SEQUENCER = "sequencer" - // RPC is the RPC component identifier. + // RPC is the RPC component identifier RPC = "rpc" - // SYNCHRONIZER is the synchronizer component identifier. + // SYNCHRONIZER is the synchronizer component identifier SYNCHRONIZER = "synchronizer" - // BROADCAST is the broadcast component identifier. - BROADCAST = "broadcast-trusted-state" + // ETHTXMANAGER is the service that manages the tx sent to L1 + ETHTXMANAGER = "eth-tx-manager" + // L2GASPRICER is the l2 gas pricer component identifier + L2GASPRICER = "l2gaspricer" + // SEQUENCE_SENDER is the sequence sender component identifier + SEQUENCE_SENDER = "sequence-sender" ) var ( @@ -43,20 +39,14 @@ var ( } networkFlag = cli.StringFlag{ Name: config.FlagNetwork, - Aliases: []string{"n"}, - Usage: "Network: mainnet, testnet, internaltestnet, local, custom, merge. By default it uses mainnet", - Required: false, + Aliases: []string{"net"}, + Usage: "Load default network configuration. Supported values: [`mainnet`, `testnet`, `custom`]", + Required: true, } customNetworkFlag = cli.StringFlag{ - Name: config.FlagNetworkCfg, - Aliases: []string{"nc"}, - Usage: "Custom network configuration `FILE` when using --network custom parameter", - } - baseNetworkFlag = cli.StringFlag{ - Name: config.FlagNetworkBase, - Aliases: []string{"nb"}, - Usage: "Base existing network configuration to be merged with the custom configuration passed with --network-cfg, by default it uses internaltestnet", - Value: "internaltestnet", + Name: config.FlagCustomNetwork, + Aliases: []string{"net-file"}, + Usage: "Load the network configuration file if --network=custom", Required: false, } yesFlag = cli.BoolFlag{ @@ -70,7 +60,7 @@ var ( Aliases: []string{"co"}, Usage: "List of components to run", Required: false, - Value: cli.NewStringSlice(AGGREGATOR, SEQUENCER, RPC, SYNCHRONIZER), + Value: cli.NewStringSlice(AGGREGATOR, SEQUENCER, RPC, SYNCHRONIZER, ETHTXMANAGER, L2GASPRICER, SEQUENCE_SENDER), } httpAPIFlag = cli.StringSliceFlag{ Name: config.FlagHTTPAPI, @@ -79,17 +69,20 @@ var ( Required: false, Value: cli.NewStringSlice(jsonrpc.APIEth, jsonrpc.APINet, jsonrpc.APIZKEVM, jsonrpc.APITxPool, jsonrpc.APIWeb3), } + migrationsFlag = cli.BoolFlag{ + Name: config.FlagMigrations, + Aliases: []string{"mig"}, + Usage: "Blocks the migrations in stateDB to not run them", + Required: false, + } ) func main() { app := cli.NewApp() app.Name = appName - app.Version = version + app.Version = zkevm.Version flags := []cli.Flag{ &configFileFlag, - &networkFlag, - &customNetworkFlag, - &baseNetworkFlag, &yesFlag, &componentsFlag, &httpAPIFlag, @@ -106,19 +99,40 @@ func main() { Aliases: []string{}, Usage: "Run the zkevm-node", Action: start, - Flags: flags, + Flags: append(flags, &networkFlag, &customNetworkFlag, &migrationsFlag), }, { Name: "approve", Aliases: []string{"ap"}, Usage: "Approve tokens to be spent by the smart contract", Action: approveTokens, - Flags: append(flags, &cli.StringFlag{ - Name: config.FlagAmount, - Aliases: []string{"am"}, - Usage: "Amount that is gonna be approved", - Required: true, - }, + Flags: append(flags, + &cli.StringFlag{ + Name: config.FlagKeyStorePath, + Aliases: []string{""}, + Usage: "the path of the key store file containing the private key of the account going to sign and approve the tokens", + Required: true, + }, + &cli.StringFlag{ + Name: config.FlagPassword, + Aliases: []string{"pw"}, + Usage: "the password do decrypt the key store file", + Required: true, + }, + &cli.StringFlag{ + Name: config.FlagAmount, + Aliases: []string{"am"}, + Usage: "Amount that is gonna be approved", + Required: false, + }, + &cli.StringFlag{ + Name: config.FlagMaxAmount, + Aliases: []string{"mam"}, + Usage: "Maximum amount is gonna be approved", + Required: false, + }, + &networkFlag, + &customNetworkFlag, ), }, { diff --git a/cmd/run.go b/cmd/run.go index 1433081bad..cd20d9c9eb 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -2,36 +2,42 @@ package main import ( "context" - "io/ioutil" - "math/big" + "fmt" + "net" + "net/http" + "net/http/pprof" "os" "os/signal" - "path/filepath" - "strings" + "runtime" + "time" + "github.com/0xPolygonHermez/zkevm-node" "github.com/0xPolygonHermez/zkevm-node/aggregator" "github.com/0xPolygonHermez/zkevm-node/config" "github.com/0xPolygonHermez/zkevm-node/db" "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/event/pgeventstorage" "github.com/0xPolygonHermez/zkevm-node/gasprice" "github.com/0xPolygonHermez/zkevm-node/jsonrpc" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" + "github.com/0xPolygonHermez/zkevm-node/metrics" "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/pricegetter" "github.com/0xPolygonHermez/zkevm-node/sequencer" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" + "github.com/0xPolygonHermez/zkevm-node/sequencesender" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + executorpb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" "github.com/0xPolygonHermez/zkevm-node/synchronizer" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" "github.com/jackc/pgx/v4/pgxpool" + "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/urfave/cli/v2" - "google.golang.org/grpc" ) func start(cliCtx *cli.Context) error { @@ -40,76 +46,206 @@ func start(cliCtx *cli.Context) error { return err } setupLog(c.Log) - runStateMigrations(c.StateDB) - stateSqlDB, err := db.NewSQLDB(c.StateDB) - if err != nil { - log.Fatal(err) + + if c.Log.Environment == log.EnvironmentDevelopment { + zkevm.PrintVersion(os.Stdout) + log.Info("Starting application") + } else if c.Log.Environment == log.EnvironmentProduction { + logVersion() } - var ( - grpcClientConns []*grpc.ClientConn - cancelFuncs []context.CancelFunc - etherman *etherman.Client - ) + if c.Metrics.Enabled { + metrics.Init() + } + components := cliCtx.StringSlice(config.FlagComponents) + + // Only runs migration if the component is the synchronizer and if the flag is deactivated + if !cliCtx.Bool(config.FlagMigrations) { + for _, comp := range components { + if comp == SYNCHRONIZER { + runStateMigrations(c.StateDB) + } + } + } + checkStateMigrations(c.StateDB) + + // Decide if this node instance needs an executor and/or a state tree + var needsExecutor, needsStateTree bool - if strings.Contains(cliCtx.String(config.FlagComponents), AGGREGATOR) || - strings.Contains(cliCtx.String(config.FlagComponents), SEQUENCER) || - strings.Contains(cliCtx.String(config.FlagComponents), SYNCHRONIZER) || - strings.Contains(cliCtx.String(config.FlagComponents), RPC) { - var err error - etherman, err = newEtherman(*c) + for _, component := range components { + switch component { + case SEQUENCER, RPC, SYNCHRONIZER: + needsExecutor = true + needsStateTree = true + } + } + + // Event log + var eventLog *event.EventLog + var eventStorage event.Storage + + if c.EventLog.DB.Name != "" { + eventStorage, err = pgeventstorage.NewPostgresEventStorage(c.EventLog.DB) if err != nil { log.Fatal(err) } - - // READ CHAIN ID FROM POE SC - chainID, err := etherman.GetL2ChainID() + } else { + eventStorage, err = nileventstorage.NewNilEventStorage() if err != nil { log.Fatal(err) } + } + eventLog = event.NewEventLog(c.EventLog, eventStorage) - c.NetworkConfig.L2ChainID = chainID - log.Infof("Chain ID read from POE SC = %v", c.NetworkConfig.L2ChainID) + // Core State DB + stateSqlDB, err := db.NewSQLDB(c.StateDB) + if err != nil { + log.Fatal(err) } + var ( + cancelFuncs []context.CancelFunc + etherman *etherman.Client + ) + + etherman, err = newEtherman(*c) + if err != nil { + log.Fatal(err) + } + + // READ CHAIN ID FROM POE SC + l2ChainID, err := etherman.GetL2ChainID() + if err != nil { + log.Fatal(err) + } + // Read Fork ID FROM POE SC + forkIDIntervals, err := etherman.GetForks(cliCtx.Context, c.NetworkConfig.Genesis.GenesisBlockNum) + if err != nil { + log.Fatal("error getting forks. Please check the configuration. Error: ", err) + } else if len(forkIDIntervals) == 0 { + log.Fatal("error: no forkID received. It should receive at least one, please check the configuration...") + } + + currentForkID := forkIDIntervals[len(forkIDIntervals)-1].ForkId + + c.Aggregator.ChainID = l2ChainID + c.Aggregator.ForkId = currentForkID + log.Infof("Chain ID read from POE SC = %v", l2ChainID) + ctx := context.Background() - st := newState(ctx, c, stateSqlDB) + st := newState(ctx, c, l2ChainID, forkIDIntervals, stateSqlDB, eventLog, needsExecutor, needsStateTree) + + ethTxManagerStorage, err := ethtxmanager.NewPostgresStorage(c.StateDB) + if err != nil { + log.Fatal(err) + } - ethTxManager := ethtxmanager.New(c.EthTxManager, etherman) + etm := ethtxmanager.New(c.EthTxManager, etherman, ethTxManagerStorage, st) - for _, item := range cliCtx.StringSlice(config.FlagComponents) { - switch item { + ev := &event.Event{ + ReceivedAt: time.Now(), + Source: event.Source_Node, + Level: event.Level_Info, + EventID: event.EventID_NodeComponentStarted, + } + + var poolInstance *pool.Pool + + for _, component := range components { + switch component { case AGGREGATOR: - log.Info("Running aggregator") - c.Aggregator.ChainID = c.NetworkConfig.L2ChainID - c.Aggregator.ProverURIs = c.Provers.ProverURIs - go runAggregator(ctx, c.Aggregator, etherman, ethTxManager, st, grpcClientConns) + ev.Component = event.Component_Aggregator + ev.Description = "Running aggregator" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + go runAggregator(ctx, c.Aggregator, etherman, etm, st) case SEQUENCER: - log.Info("Running sequencer") - poolInstance := createPool(c.PoolDB, c.NetworkConfig, st) - gpe := createGasPriceEstimator(c.GasPriceEstimator, st, poolInstance) - seq := createSequencer(*c, poolInstance, st, etherman, ethTxManager, gpe) + ev.Component = event.Component_Sequencer + ev.Description = "Running sequencer" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + if poolInstance == nil { + poolInstance = createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st, eventLog) + } + seq := createSequencer(*c, poolInstance, ethTxManagerStorage, st, eventLog) go seq.Start(ctx) + case SEQUENCE_SENDER: + ev.Component = event.Component_Sequence_Sender + ev.Description = "Running sequence sender" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + if poolInstance == nil { + poolInstance = createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st, eventLog) + } + seqSender := createSequenceSender(*c, poolInstance, ethTxManagerStorage, st, eventLog) + go seqSender.Start(ctx) case RPC: - log.Info("Running JSON-RPC server") - runRPCMigrations(c.RPC.DB) - poolInstance := createPool(c.PoolDB, c.NetworkConfig, st) - gpe := createGasPriceEstimator(c.GasPriceEstimator, st, poolInstance) + ev.Component = event.Component_RPC + ev.Description = "Running JSON-RPC server" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + if poolInstance == nil { + poolInstance = createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st, eventLog) + } + if c.RPC.EnableL2SuggestedGasPricePolling { + // Needed for rejecting transactions with too low gas price + poolInstance.StartPollingMinSuggestedGasPrice(ctx) + } apis := map[string]bool{} for _, a := range cliCtx.StringSlice(config.FlagHTTPAPI) { apis[a] = true } - go runJSONRPCServer(*c, poolInstance, st, gpe, apis) + go runJSONRPCServer(*c, l2ChainID, poolInstance, st, apis) case SYNCHRONIZER: - log.Info("Running synchronizer") - go runSynchronizer(*c, etherman, st) - case BROADCAST: - log.Info("Running broadcast service") - go runBroadcastServer(c.BroadcastServer, st) + ev.Component = event.Component_Synchronizer + ev.Description = "Running synchronizer" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + if poolInstance == nil { + poolInstance = createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st, eventLog) + } + go runSynchronizer(*c, etherman, etm, st, poolInstance) + case ETHTXMANAGER: + ev.Component = event.Component_EthTxManager + ev.Description = "Running eth tx manager service" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + etm := createEthTxManager(*c, ethTxManagerStorage, st) + go etm.Start() + case L2GASPRICER: + ev.Component = event.Component_GasPricer + ev.Description = "Running L2 gasPricer" + err := eventLog.LogEvent(ctx, ev) + if err != nil { + log.Fatal(err) + } + if poolInstance == nil { + poolInstance = createPool(c.Pool, c.NetworkConfig.L2BridgeAddr, l2ChainID, st, eventLog) + } + go runL2GasPriceSuggester(c.L2GasPriceSuggester, st, poolInstance, etherman) } } - waitSignal(grpcClientConns, cancelFuncs) + if c.Metrics.Enabled { + go startMetricsHttpServer(c.Metrics) + } + + if c.Metrics.ProfilingEnabled { + go startProfilingHttpServer(c.Metrics) + } + waitSignal(cancelFuncs) return nil } @@ -122,15 +258,19 @@ func runStateMigrations(c db.Config) { runMigrations(c, db.StateMigrationName) } -func runPoolMigrations(c db.Config) { - runMigrations(c, db.PoolMigrationName) +func checkStateMigrations(c db.Config) { + err := db.CheckMigrations(c, db.StateMigrationName) + if err != nil { + log.Fatal(err) + } } -func runRPCMigrations(c db.Config) { - runMigrations(c, db.RPCMigrationName) +func runPoolMigrations(c db.Config) { + runMigrations(c, db.PoolMigrationName) } func runMigrations(c db.Config, name string) { + log.Infof("running migrations for %v", name) err := db.RunMigrationsUp(c, name) if err != nil { log.Fatal(err) @@ -138,19 +278,34 @@ func runMigrations(c db.Config, name string) { } func newEtherman(c config.Config) (*etherman.Client, error) { - auth, err := newAuthFromKeystore(c.Etherman.PrivateKeyPath, c.Etherman.PrivateKeyPassword, c.NetworkConfig.L1ChainID) - if err != nil { - return nil, err - } - etherman, err := etherman.NewClient(c.Etherman, auth, c.NetworkConfig.PoEAddr, c.NetworkConfig.MaticAddr, c.NetworkConfig.GlobalExitRootManagerAddr) + etherman, err := etherman.NewClient(c.Etherman, c.NetworkConfig.L1Config) if err != nil { return nil, err } return etherman, nil } -func runSynchronizer(cfg config.Config, etherman *etherman.Client, st *state.State) { - sy, err := synchronizer.NewSynchronizer(cfg.IsTrustedSequencer, etherman, st, cfg.NetworkConfig.GenBlockNumber, cfg.NetworkConfig.Genesis, cfg.Synchronizer) +func runSynchronizer(cfg config.Config, etherman *etherman.Client, ethTxManager *ethtxmanager.Client, st *state.State, pool *pool.Pool) { + var trustedSequencerURL string + var err error + if !cfg.IsTrustedSequencer { + if cfg.Synchronizer.TrustedSequencerURL != "" { + trustedSequencerURL = cfg.Synchronizer.TrustedSequencerURL + } else { + log.Debug("getting trusted sequencer URL from smc") + trustedSequencerURL, err = etherman.GetTrustedSequencerURL() + if err != nil { + log.Fatal("error getting trusted sequencer URI. Error: %v", err) + } + } + log.Debug("trustedSequencerURL ", trustedSequencerURL) + } + zkEVMClient := client.NewClient(trustedSequencerURL) + + sy, err := synchronizer.NewSynchronizer( + cfg.IsTrustedSequencer, etherman, st, pool, ethTxManager, + zkEVMClient, cfg.NetworkConfig.Genesis, cfg.Synchronizer, + ) if err != nil { log.Fatal(err) } @@ -159,71 +314,71 @@ func runSynchronizer(cfg config.Config, etherman *etherman.Client, st *state.Sta } } -func runJSONRPCServer(c config.Config, pool *pool.Pool, st *state.State, gpe gasPriceEstimator, apis map[string]bool) { - storage, err := jsonrpc.NewPostgresStorage(c.RPC.DB) - if err != nil { - log.Fatal(err) - } - +func runJSONRPCServer(c config.Config, chainID uint64, pool *pool.Pool, st *state.State, apis map[string]bool) { + storage := jsonrpc.NewStorage() c.RPC.MaxCumulativeGasUsed = c.Sequencer.MaxCumulativeGasUsed - c.RPC.ChainID = c.NetworkConfig.L2ChainID - if err := jsonrpc.NewServer(c.RPC, pool, st, gpe, storage, apis).Start(); err != nil { + if err := jsonrpc.NewServer(c.RPC, chainID, pool, st, storage, apis).Start(); err != nil { log.Fatal(err) } } -func createSequencer(c config.Config, pool *pool.Pool, state *state.State, etherman *etherman.Client, - ethTxManager *ethtxmanager.Client, gpe gasPriceEstimator) *sequencer.Sequencer { - pg, err := pricegetter.NewClient(c.PriceGetter) +func createSequencer(cfg config.Config, pool *pool.Pool, etmStorage *ethtxmanager.PostgresStorage, st *state.State, eventLog *event.EventLog) *sequencer.Sequencer { + etherman, err := newEtherman(cfg) if err != nil { log.Fatal(err) } - seq, err := sequencer.New(c.Sequencer, pool, state, etherman, pg, ethTxManager, gpe) + ethTxManager := ethtxmanager.New(cfg.EthTxManager, etherman, etmStorage, st) + + seq, err := sequencer.New(cfg.Sequencer, pool, st, etherman, ethTxManager, eventLog) if err != nil { log.Fatal(err) } return seq } -func runAggregator(ctx context.Context, c aggregator.Config, ethman *etherman.Client, ethTxManager *ethtxmanager.Client, state *state.State, grpcClientConns []*grpc.ClientConn) { - agg, err := aggregator.NewAggregator(c, state, ethTxManager, ethman, grpcClientConns) +func createSequenceSender(cfg config.Config, pool *pool.Pool, etmStorage *ethtxmanager.PostgresStorage, st *state.State, eventLog *event.EventLog) *sequencesender.SequenceSender { + etherman, err := newEtherman(cfg) if err != nil { log.Fatal(err) } - agg.Start(ctx) -} -func runBroadcastServer(c broadcast.ServerConfig, st *state.State) { - s := grpc.NewServer() + for _, privateKey := range cfg.SequenceSender.PrivateKeys { + _, err := etherman.LoadAuthFromKeyStore(privateKey.Path, privateKey.Password) + if err != nil { + log.Fatal(err) + } + } - broadcastSrv := broadcast.NewServer(&c, st) - pb.RegisterBroadcastServiceServer(s, broadcastSrv) + ethTxManager := ethtxmanager.New(cfg.EthTxManager, etherman, etmStorage, st) - broadcastSrv.Start() -} + seqSender, err := sequencesender.New(cfg.SequenceSender, st, etherman, ethTxManager, eventLog) + if err != nil { + log.Fatal(err) + } -// gasPriceEstimator interface for gas price estimator. -type gasPriceEstimator interface { - GetAvgGasPrice(ctx context.Context) (*big.Int, error) - UpdateGasPriceAvg(newValue *big.Int) + return seqSender } -// createGasPriceEstimator init gas price gasPriceEstimator based on type in config. -func createGasPriceEstimator(cfg gasprice.Config, state *state.State, pool *pool.Pool) gasPriceEstimator { - switch cfg.Type { - case gasprice.AllBatchesType: - return gasprice.NewEstimatorAllBatches() - case gasprice.LastNBatchesType: - return gasprice.NewEstimatorLastNL2Blocks(cfg, state) - case gasprice.DefaultType: - return gasprice.NewDefaultEstimator(cfg, pool) +func runAggregator(ctx context.Context, c aggregator.Config, etherman *etherman.Client, ethTxManager *ethtxmanager.Client, st *state.State) { + agg, err := aggregator.New(c, st, ethTxManager, etherman) + if err != nil { + log.Fatal(err) + } + err = agg.Start(ctx) + if err != nil { + log.Fatal(err) } - return nil } -func waitSignal(conns []*grpc.ClientConn, cancelFuncs []context.CancelFunc) { +// runL2GasPriceSuggester init gas price gasPriceEstimator based on type in config. +func runL2GasPriceSuggester(cfg gasprice.Config, state *state.State, pool *pool.Pool, etherman *etherman.Client) { + ctx := context.Background() + gasprice.NewL2GasPriceSuggester(ctx, cfg, pool, etherman, state) +} + +func waitSignal(cancelFuncs []context.CancelFunc) { signals := make(chan os.Signal, 1) signal.Notify(signals, os.Interrupt) @@ -233,12 +388,6 @@ func waitSignal(conns []*grpc.ClientConn, cancelFuncs []context.CancelFunc) { log.Info("terminating application gracefully...") exitStatus := 0 - for _, conn := range conns { - if err := conn.Close(); err != nil { - log.Errorf("Could not properly close gRPC connection: %v", err) - exitStatus = -1 - } - } for _, cancel := range cancelFuncs { cancel() } @@ -247,55 +396,122 @@ func waitSignal(conns []*grpc.ClientConn, cancelFuncs []context.CancelFunc) { } } -func newKeyFromKeystore(path, password string) (*keystore.Key, error) { - if path == "" && password == "" { - return nil, nil +func newState(ctx context.Context, c *config.Config, l2ChainID uint64, forkIDIntervals []state.ForkIDInterval, sqlDB *pgxpool.Pool, eventLog *event.EventLog, needsExecutor, needsStateTree bool) *state.State { + stateDb := state.NewPostgresStorage(sqlDB) + + // Executor + var executorClient executorpb.ExecutorServiceClient + if needsExecutor { + executorClient, _, _ = executor.NewExecutorClient(ctx, c.Executor) } - keystoreEncrypted, err := ioutil.ReadFile(filepath.Clean(path)) - if err != nil { - return nil, err + + // State Tree + var stateTree *merkletree.StateTree + if needsStateTree { + stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, c.MTClient) + stateTree = merkletree.NewStateTree(stateDBClient) } - key, err := keystore.DecryptKey(keystoreEncrypted, password) - if err != nil { - return nil, err + + stateCfg := state.Config{ + MaxCumulativeGasUsed: c.Sequencer.MaxCumulativeGasUsed, + ChainID: l2ChainID, + ForkIDIntervals: forkIDIntervals, } - return key, nil + + st := state.NewState(stateCfg, stateDb, executorClient, stateTree, eventLog) + return st } -func newAuthFromKeystore(path, password string, chainID uint64) (*bind.TransactOpts, error) { - key, err := newKeyFromKeystore(path, password) +func createPool(cfgPool pool.Config, l2BridgeAddr common.Address, l2ChainID uint64, st *state.State, eventLog *event.EventLog) *pool.Pool { + runPoolMigrations(cfgPool.DB) + poolStorage, err := pgpoolstorage.NewPostgresPoolStorage(cfgPool.DB) if err != nil { log.Fatal(err) } - log.Info("addr: ", key.Address.Hex()) - auth, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, new(big.Int).SetUint64(chainID)) + poolInstance := pool.NewPool(cfgPool, poolStorage, st, l2BridgeAddr, l2ChainID, eventLog) + return poolInstance +} + +func createEthTxManager(cfg config.Config, etmStorage *ethtxmanager.PostgresStorage, st *state.State) *ethtxmanager.Client { + etherman, err := newEtherman(cfg) if err != nil { log.Fatal(err) } - return auth, nil -} - -func newState(ctx context.Context, c *config.Config, sqlDB *pgxpool.Pool) *state.State { - stateDb := state.NewPostgresStorage(sqlDB) - executorClient, _, _ := executor.NewExecutorClient(ctx, c.Executor) - stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, c.MTClient) - stateTree := merkletree.NewStateTree(stateDBClient) - stateCfg := state.Config{ - MaxCumulativeGasUsed: c.Sequencer.MaxCumulativeGasUsed, - ChainID: c.NetworkConfig.L2ChainID, + for _, privateKey := range cfg.EthTxManager.PrivateKeys { + _, err := etherman.LoadAuthFromKeyStore(privateKey.Path, privateKey.Password) + if err != nil { + log.Fatal(err) + } } + etm := ethtxmanager.New(cfg.EthTxManager, etherman, etmStorage, st) + return etm +} - st := state.NewState(stateCfg, stateDb, executorClient, stateTree) - return st +func startProfilingHttpServer(c metrics.Config) { + const two = 2 + mux := http.NewServeMux() + address := fmt.Sprintf("%s:%d", c.ProfilingHost, c.ProfilingPort) + lis, err := net.Listen("tcp", address) + if err != nil { + log.Errorf("failed to create tcp listener for profiling: %v", err) + return + } + mux.HandleFunc(metrics.ProfilingIndexEndpoint, pprof.Index) + mux.HandleFunc(metrics.ProfileEndpoint, pprof.Profile) + mux.HandleFunc(metrics.ProfilingCmdEndpoint, pprof.Cmdline) + mux.HandleFunc(metrics.ProfilingSymbolEndpoint, pprof.Symbol) + mux.HandleFunc(metrics.ProfilingTraceEndpoint, pprof.Trace) + profilingServer := &http.Server{ + Handler: mux, + ReadHeaderTimeout: two * time.Minute, + ReadTimeout: two * time.Minute, + } + log.Infof("profiling server listening on port %d", c.ProfilingPort) + if err := profilingServer.Serve(lis); err != nil { + if err == http.ErrServerClosed { + log.Warnf("http server for profiling stopped") + return + } + log.Errorf("closed http connection for profiling server: %v", err) + return + } } -func createPool(poolDBConfig db.Config, networkConfig config.NetworkConfig, st *state.State) *pool.Pool { - runPoolMigrations(poolDBConfig) - poolStorage, err := pgpoolstorage.NewPostgresPoolStorage(poolDBConfig) +func startMetricsHttpServer(c metrics.Config) { + const ten = 10 + mux := http.NewServeMux() + address := fmt.Sprintf("%s:%d", c.Host, c.Port) + lis, err := net.Listen("tcp", address) if err != nil { - log.Fatal(err) + log.Errorf("failed to create tcp listener for metrics: %v", err) + return } - poolInstance := pool.NewPool(poolStorage, st, networkConfig.L2BridgeAddr, networkConfig.L2ChainID) - return poolInstance + mux.Handle(metrics.Endpoint, promhttp.Handler()) + + metricsServer := &http.Server{ + Handler: mux, + ReadHeaderTimeout: ten * time.Second, + ReadTimeout: ten * time.Second, + } + log.Infof("metrics server listening on port %d", c.Port) + if err := metricsServer.Serve(lis); err != nil { + if err == http.ErrServerClosed { + log.Warnf("http server for metrics stopped") + return + } + log.Errorf("closed http connection for metrics server: %v", err) + return + } +} + +func logVersion() { + log.Infow("Starting application", + // node version is already logged by default + "gitRevision", zkevm.GitRev, + "gitBranch", zkevm.GitBranch, + "goVersion", runtime.Version(), + "built", zkevm.BuildDate, + "os/arch", fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + ) } diff --git a/cmd/version.go b/cmd/version.go index d1cb1e98f4..cd85629245 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,14 +1,13 @@ package main import ( - "fmt" + "os" + "github.com/0xPolygonHermez/zkevm-node" "github.com/urfave/cli/v2" ) func versionCmd(*cli.Context) error { - fmt.Printf("Version = \"%v\"\n", version) - fmt.Printf("Build = \"%v\"\n", commit) - fmt.Printf("Date = \"%v\"\n", date) + zkevm.PrintVersion(os.Stdout) return nil } diff --git a/config/config.debug.toml b/config/config.debug.toml deleted file mode 100644 index 12063e8017..0000000000 --- a/config/config.debug.toml +++ /dev/null @@ -1,106 +0,0 @@ -IsTrustedSequencer = true - -[Log] -Level = "debug" -Outputs = ["stdout"] - -[StateDB] -User = "state_user" -Password = "state_password" -Name = "state_db" -Host = "localhost" -Port = "5432" -EnableLog = false -MaxConns = 10 - -[PoolDB] -User = "pool_user" -Password = "pool_password" -Name = "pool_db" -Host = "localhost" -Port = "5433" -EnableLog = false -MaxConns = 10 - -[Etherman] -URL = "http://localhost:8545" -PrivateKeyPath = "../test/test.keystore" -PrivateKeyPassword = "testonly" - -[EthTxManager] -MaxSendBatchTxRetries = 10 -MaxVerifyBatchTxRetries = 10 -FrequencyForResendingFailedSendBatches = "1s" -FrequencyForResendingFailedVerifyBatch = "1s" -WaitTxToBeMined = "2m" -PercentageToIncreaseGasPrice = 10 -PercentageToIncreaseGasLimit = 10 - -[RPC] -Host = "0.0.0.0" -Port = 8123 -MaxRequestsPerIPAndSecond = 10000 -SequencerNodeURI = "" -BroadcastURI = "127.0.0.1:61090" -DefaultSenderAddress = "0x1111111111111111111111111111111111111111" - [RPC.DB] - User = "rpc_user" - Password = "rpc_password" - Name = "rpc_db" - Host = "localhost" - Port = "5434" - EnableLog = false - MaxConns = 10 - -[Synchronizer] -SyncInterval = "5s" -SyncChunkSize = 100 -TrustedSequencerURI = "" - -[Sequencer] -MaxSequenceSize = "2000000" -WaitPeriodPoolIsEmpty = "1s" -WaitPeriodSendSequence = "15s" -LastBatchVirtualizationTimeMaxWaitPeriod = "300s" -WaitBlocksToUpdateGER = 10 -MaxTimeForBatchToBeOpen = "15s" -BlocksAmountForTxsToBeDeleted = 100 -FrequencyToCheckTxsForDelete = "12h" -MaxCumulativeGasUsed = 30000000 -MaxKeccakHashes = 468 -MaxPoseidonHashes = 279620 -MaxPoseidonPaddings = 149796 -MaxMemAligns = 262144 -MaxArithmetics = 262144 -MaxBinaries = 262144 -MaxSteps = 8388608 - [Sequencer.ProfitabilityChecker] - SendBatchesEvenWhenNotProfitable = "true" - -[Aggregator] -IntervalToConsolidateState = "10s" -IntervalFrequencyToGetProofGenerationState = "5s" -TxProfitabilityCheckerType = "acceptall" -TxProfitabilityMinReward = "1.1" - -[GasPriceEstimator] -Type = "default" -DefaultGasPriceWei = 1000000000 - -[Prover] -ProverURI = "localhost:50052" - -[MTServer] -Host = "0.0.0.0" -Port = 50060 -StoreBackend = "PostgreSQL" - -[MTClient] -URI = "127.0.0.1:50061" - -[Executor] -URI = "127.0.0.1:50071" - -[BroadcastServer] -Host = "0.0.0.0" -Port = 61090 diff --git a/config/config.go b/config/config.go index 43fe6af987..650948053b 100644 --- a/config/config.go +++ b/config/config.go @@ -9,14 +9,16 @@ import ( "github.com/0xPolygonHermez/zkevm-node/db" "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + "github.com/0xPolygonHermez/zkevm-node/event" "github.com/0xPolygonHermez/zkevm-node/gasprice" "github.com/0xPolygonHermez/zkevm-node/jsonrpc" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" + "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/pricegetter" - "github.com/0xPolygonHermez/zkevm-node/proverclient" "github.com/0xPolygonHermez/zkevm-node/sequencer" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast" + "github.com/0xPolygonHermez/zkevm-node/sequencesender" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" "github.com/0xPolygonHermez/zkevm-node/synchronizer" "github.com/mitchellh/mapstructure" @@ -29,12 +31,10 @@ const ( FlagYes = "yes" // FlagCfg is the flag for cfg. FlagCfg = "cfg" - // FlagNetwork is the flag for network. + // FlagNetwork is the flag for the network name. Valid values: ["testnet", "mainnet", "custom"]. FlagNetwork = "network" - // FlagNetworkCfg is the flag for network-cfg. - FlagNetworkCfg = "network-cfg" - // FlagNetworkBase is the flag for netwotk-base. - FlagNetworkBase = "network-base" + // FlagCustomNetwork is the flag for the custom network file. This is required if --network=custom + FlagCustomNetwork = "custom-network-file" // FlagAmount is the flag for amount. FlagAmount = "amount" // FlagRemoteMT is the flag for remote-merkletree. @@ -43,31 +43,40 @@ const ( FlagComponents = "components" // FlagHTTPAPI is the flag for http.api. FlagHTTPAPI = "http.api" + // FlagKeyStorePath is the path of the key store file containing the private key of the account going to sing and approve the tokens + FlagKeyStorePath = "key-store-path" + // FlagPassword is the password needed to decrypt the key store + FlagPassword = "password" + // FlagMigrations is the flag for migrations. + FlagMigrations = "migrations" + // FlagMaxAmount is the flag to avoid to use the flag FlagAmount + FlagMaxAmount = "max-amount" ) // Config represents the configuration of the entire Hermez Node type Config struct { - IsTrustedSequencer bool `mapstructure:"IsTrustedSequencer"` - Log log.Config - Etherman etherman.Config - EthTxManager ethtxmanager.Config - RPC jsonrpc.Config - Synchronizer synchronizer.Config - Sequencer sequencer.Config - PriceGetter pricegetter.Config - Aggregator aggregator.Config - Provers proverclient.Config - NetworkConfig NetworkConfig - GasPriceEstimator gasprice.Config - Executor executor.Config - BroadcastServer broadcast.ServerConfig - MTClient merkletree.Config - StateDB db.Config - PoolDB db.Config + IsTrustedSequencer bool `mapstructure:"IsTrustedSequencer"` + Log log.Config + Etherman etherman.Config + EthTxManager ethtxmanager.Config + Pool pool.Config + RPC jsonrpc.Config + Synchronizer synchronizer.Config + Sequencer sequencer.Config + SequenceSender sequencesender.Config + PriceGetter pricegetter.Config + Aggregator aggregator.Config + NetworkConfig NetworkConfig + L2GasPriceSuggester gasprice.Config + Executor executor.Config + MTClient merkletree.Config + StateDB db.Config + Metrics metrics.Config + EventLog event.Config } -// Load loads the configuration -func Load(ctx *cli.Context) (*Config, error) { +// Default parses the default configuration values. +func Default() (*Config, error) { var cfg Config viper.SetConfigType("toml") @@ -79,6 +88,15 @@ func Load(ctx *cli.Context) (*Config, error) { if err != nil { return nil, err } + return &cfg, nil +} + +// Load loads the configuration +func Load(ctx *cli.Context) (*Config, error) { + cfg, err := Default() + if err != nil { + return nil, err + } configFilePath := ctx.String(FlagCfg) if configFilePath != "" { dirName, fileName := filepath.Split(configFilePath) @@ -105,18 +123,16 @@ func Load(ctx *cli.Context) (*Config, error) { } } - err = viper.Unmarshal(&cfg, viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())) + decodeHooks := []viper.DecoderConfigOption{ + // this allows arrays to be decoded from env var separated by ",", example: MY_VAR="value1,value2,value3" + viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(mapstructure.TextUnmarshallerHookFunc(), mapstructure.StringToSliceHookFunc(","))), + } + + err = viper.Unmarshal(&cfg, decodeHooks...) if err != nil { return nil, err } // Load genesis parameters cfg.loadNetworkConfig(ctx) - /* - cfgJSON, err := json.MarshalIndent(cfg, "", " ") - if err != nil { - return nil, err - } - log.Debugf("Configuration loaded: \n%s\n", string(cfgJSON)) - */ - return &cfg, nil + return cfg, nil } diff --git a/config/config.local.toml b/config/config.local.toml deleted file mode 100644 index 93aba9d703..0000000000 --- a/config/config.local.toml +++ /dev/null @@ -1,106 +0,0 @@ -IsTrustedSequencer = true - -[Log] -Level = "debug" -Outputs = ["stdout"] - -[StateDB] -User = "state_user" -Password = "state_password" -Name = "state_db" -Host = "zkevm-state-db" -Port = "5432" -EnableLog = false -MaxConns = 200 - -[PoolDB] -User = "pool_user" -Password = "pool_password" -Name = "pool_db" -Host = "zkevm-pool-db" -Port = "5432" -EnableLog = false -MaxConns = 200 - -[Etherman] -URL = "http://zkevm-mock-l1-network:8545" -PrivateKeyPath = "./test/test.keystore" -PrivateKeyPassword = "testonly" - -[EthTxManager] -MaxSendBatchTxRetries = 10 -MaxVerifyBatchTxRetries = 10 -FrequencyForResendingFailedSendBatches = "1s" -FrequencyForResendingFailedVerifyBatch = "1s" -WaitTxToBeMined = "2m" -PercentageToIncreaseGasPrice = 10 -PercentageToIncreaseGasLimit = 10 - -[RPC] -Host = "0.0.0.0" -Port = 8123 -MaxRequestsPerIPAndSecond = 5000 -SequencerNodeURI = "" -BroadcastURI = "127.0.0.1:61090" -DefaultSenderAddress = "0x1111111111111111111111111111111111111111" - [RPC.DB] - User = "rpc_user" - Password = "rpc_password" - Name = "rpc_db" - Host = "zkevm-rpc-db" - Port = "5432" - EnableLog = false - MaxConns = 10 - -[Synchronizer] -SyncInterval = "1s" -SyncChunkSize = 100 -TrustedSequencerURI = "" - -[Sequencer] -MaxSequenceSize = "2000000" -WaitPeriodPoolIsEmpty = "1s" -WaitPeriodSendSequence = "15s" -LastBatchVirtualizationTimeMaxWaitPeriod = "300s" -WaitBlocksToUpdateGER = 10 -MaxTimeForBatchToBeOpen = "15s" -BlocksAmountForTxsToBeDeleted = 100 -FrequencyToCheckTxsForDelete = "12h" -MaxCumulativeGasUsed = 30000000 -MaxKeccakHashes = 468 -MaxPoseidonHashes = 279620 -MaxPoseidonPaddings = 149796 -MaxMemAligns = 262144 -MaxArithmetics = 262144 -MaxBinaries = 262144 -MaxSteps = 8388608 - [Sequencer.ProfitabilityChecker] - SendBatchesEvenWhenNotProfitable = "true" - -[Aggregator] -IntervalToConsolidateState = "10s" -IntervalFrequencyToGetProofGenerationState = "5s" -TxProfitabilityCheckerType = "acceptall" -TxProfitabilityMinReward = "1.1" - -[GasPriceEstimator] -Type = "default" -DefaultGasPriceWei = 1000000000 - -[Provers] -ProverURIs = ["zkevm-prover:50052"] - -[MTServer] -Host = "0.0.0.0" -Port = 50060 -StoreBackend = "PostgreSQL" - -[MTClient] -URI = "zkevm-prover:50061" - -[Executor] -URI = "zkevm-prover:50071" - -[BroadcastServer] -Host = "0.0.0.0" -Port = 61090 diff --git a/config/config_test.go b/config/config_test.go index c41541eb0f..a7382e11bf 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -3,15 +3,19 @@ package config_test import ( "flag" "math/big" + "os" "reflect" "strings" "testing" "time" + "github.com/0xPolygonHermez/zkevm-node/aggregator" "github.com/0xPolygonHermez/zkevm-node/config" "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/pricegetter" - "github.com/0xPolygonHermez/zkevm-node/sequencer" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" ) @@ -21,6 +25,18 @@ func Test_Defaults(t *testing.T) { path string expectedValue interface{} }{ + { + path: "Log.Environment", + expectedValue: log.LogEnvironment("development"), + }, + { + path: "Log.Level", + expectedValue: "info", + }, + { + path: "Log.Outputs", + expectedValue: []string{"stderr"}, + }, { path: "Synchronizer.SyncChunkSize", expectedValue: uint64(100), @@ -38,16 +54,12 @@ func Test_Defaults(t *testing.T) { expectedValue: types.NewDuration(1 * time.Second), }, { - path: "Sequencer.LastBatchVirtualizationTimeMaxWaitPeriod", - expectedValue: types.NewDuration(300 * time.Second), + path: "Sequencer.MaxTxsPerBatch", + expectedValue: uint64(150), }, { - path: "Sequencer.WaitBlocksToUpdateGER", - expectedValue: uint64(10), - }, - { - path: "Sequencer.MaxTimeForBatchToBeOpen", - expectedValue: types.NewDuration(15 * time.Second), + path: "Sequencer.MaxBatchBytesSize", + expectedValue: uint64(129848), }, { path: "Sequencer.BlocksAmountForTxsToBeDeleted", @@ -57,60 +69,172 @@ func Test_Defaults(t *testing.T) { path: "Sequencer.FrequencyToCheckTxsForDelete", expectedValue: types.NewDuration(12 * time.Hour), }, - { - path: "Sequencer.ProfitabilityChecker.SendBatchesEvenWhenNotProfitable", - expectedValue: true, - }, { path: "Sequencer.MaxCumulativeGasUsed", expectedValue: uint64(30000000), }, { path: "Sequencer.MaxKeccakHashes", - expectedValue: int32(468), + expectedValue: uint32(468), }, { path: "Sequencer.MaxPoseidonHashes", - expectedValue: int32(279620), + expectedValue: uint32(279620), }, { path: "Sequencer.MaxPoseidonPaddings", - expectedValue: int32(149796), + expectedValue: uint32(149796), }, { path: "Sequencer.MaxMemAligns", - expectedValue: int32(262144), + expectedValue: uint32(262144), }, { path: "Sequencer.MaxArithmetics", - expectedValue: int32(262144), + expectedValue: uint32(262144), }, { path: "Sequencer.MaxBinaries", - expectedValue: int32(262144), + expectedValue: uint32(262144), }, { path: "Sequencer.MaxSteps", - expectedValue: int32(8388608), + expectedValue: uint32(8388608), }, { - path: "Sequencer.MaxSequenceSize", - expectedValue: sequencer.MaxSequenceSize{Int: new(big.Int).SetInt64(2000000)}, + path: "Sequencer.TxLifetimeCheckTimeout", + expectedValue: types.NewDuration(10 * time.Minute), }, { - path: "EthTxManager.MaxSendBatchTxRetries", - expectedValue: uint32(10), + path: "Sequencer.MaxTxLifetime", + expectedValue: types.NewDuration(3 * time.Hour), + }, + { + path: "Sequencer.WeightBatchBytesSize", + expectedValue: 1, + }, + { + path: "Sequencer.WeightCumulativeGasUsed", + expectedValue: 1, + }, + { + path: "Sequencer.WeightKeccakHashes", + expectedValue: 1, + }, + { + path: "Sequencer.WeightPoseidonHashes", + expectedValue: 1, + }, + { + path: "Sequencer.WeightPoseidonPaddings", + expectedValue: 1, + }, + { + path: "Sequencer.WeightMemAligns", + expectedValue: 1, + }, + { + path: "Sequencer.WeightArithmetics", + expectedValue: 1, + }, + { + path: "Sequencer.WeightBinaries", + expectedValue: 1, + }, + { + path: "Sequencer.WeightSteps", + expectedValue: 1, + }, + { + path: "Sequencer.Finalizer.GERDeadlineTimeout", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "Sequencer.Finalizer.ForcedBatchDeadlineTimeout", + expectedValue: types.NewDuration(60 * time.Second), + }, + { + path: "Sequencer.Finalizer.SleepDuration", + expectedValue: types.NewDuration(100 * time.Millisecond), }, { - path: "EthTxManager.MaxVerifyBatchTxRetries", + path: "Sequencer.Finalizer.ResourcePercentageToCloseBatch", expectedValue: uint32(10), }, { - path: "EthTxManager.FrequencyForResendingFailedSendBatches", - expectedValue: types.NewDuration(1 * time.Second), + path: "Sequencer.Finalizer.GERFinalityNumberOfBlocks", + expectedValue: uint64(64), + }, + { + path: "Sequencer.Finalizer.ClosingSignalsManagerWaitForCheckingL1Timeout", + expectedValue: types.NewDuration(10 * time.Second), + }, + { + path: "Sequencer.Finalizer.ClosingSignalsManagerWaitForCheckingGER", + expectedValue: types.NewDuration(10 * time.Second), + }, + { + path: "Sequencer.Finalizer.ClosingSignalsManagerWaitForCheckingForcedBatches", + expectedValue: types.NewDuration(10 * time.Second), + }, + { + path: "Sequencer.Finalizer.ForcedBatchesFinalityNumberOfBlocks", + expectedValue: uint64(64), + }, + { + path: "Sequencer.Finalizer.TimestampResolution", + expectedValue: types.NewDuration(10 * time.Second), + }, + { + path: "Sequencer.DBManager.PoolRetrievalInterval", + expectedValue: types.NewDuration(500 * time.Millisecond), + }, + { + path: "Sequencer.DBManager.L2ReorgRetrievalInterval", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "Sequencer.Worker.ResourceCostMultiplier", + expectedValue: float64(1000), + }, + { + path: "SequenceSender.WaitPeriodSendSequence", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "SequenceSender.LastBatchVirtualizationTimeMaxWaitPeriod", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "SequenceSender.MaxTxSizeForL1", + expectedValue: uint64(131072), }, { - path: "EthTxManager.FrequencyForResendingFailedVerifyBatch", + path: "Etherman.URL", + expectedValue: "http://localhost:8545", + }, + { + path: "NetworkConfig.L1Config.L1ChainID", + expectedValue: uint64(5), + }, + { + path: "NetworkConfig.L1Config.ZkEVMAddr", + expectedValue: common.HexToAddress("0xa997cfD539E703921fD1e3Cf25b4c241a27a4c7A"), + }, + { + path: "NetworkConfig.L1Config.MaticAddr", + expectedValue: common.HexToAddress("0x1319D23c2F7034F52Eb07399702B040bA278Ca49"), + }, + { + path: "NetworkConfig.L1Config.GlobalExitRootManagerAddr", + expectedValue: common.HexToAddress("0x4d9427DCA0406358445bC0a8F88C26b704004f74"), + }, + { + path: "Etherman.MultiGasProvider", + expectedValue: false, + }, + { + path: "EthTxManager.FrequencyToMonitorTxs", expectedValue: types.NewDuration(1 * time.Second), }, { @@ -118,12 +242,12 @@ func Test_Defaults(t *testing.T) { expectedValue: types.NewDuration(2 * time.Minute), }, { - path: "EthTxManager.PercentageToIncreaseGasPrice", - expectedValue: uint64(10), + path: "EthTxManager.WaitTxToBeMined", + expectedValue: types.NewDuration(2 * time.Minute), }, { - path: "EthTxManager.PercentageToIncreaseGasLimit", - expectedValue: uint64(10), + path: "EthTxManager.ForcedGas", + expectedValue: uint64(0), }, { path: "PriceGetter.Type", @@ -134,12 +258,12 @@ func Test_Defaults(t *testing.T) { expectedValue: pricegetter.TokenPrice{Float: new(big.Float).SetInt64(2000)}, }, { - path: "GasPriceEstimator.DefaultGasPriceWei", - expectedValue: uint64(1000000000), + path: "L2GasPriceSuggester.DefaultGasPriceWei", + expectedValue: uint64(2000000000), }, { path: "MTClient.URI", - expectedValue: "127.0.0.1:50061", + expectedValue: "zkevm-prover:50061", }, { path: "StateDB.User", @@ -155,7 +279,7 @@ func Test_Defaults(t *testing.T) { }, { path: "StateDB.Host", - expectedValue: "localhost", + expectedValue: "zkevm-state-db", }, { path: "StateDB.Port", @@ -170,31 +294,52 @@ func Test_Defaults(t *testing.T) { expectedValue: 200, }, { - path: "PoolDB.User", + path: "Pool.MaxTxBytesSize", + expectedValue: uint64(100132), + }, + { + path: "Pool.MaxTxDataBytesSize", + expectedValue: 100000, + }, + + { + path: "Pool.DefaultMinGasPriceAllowed", + expectedValue: uint64(1000000000), + }, + { + path: "Pool.MinAllowedGasPriceInterval", + expectedValue: types.NewDuration(5 * time.Minute), + }, + { + path: "Pool.PollMinAllowedGasPriceInterval", + expectedValue: types.NewDuration(15 * time.Second), + }, + { + path: "Pool.DB.User", expectedValue: "pool_user", }, { - path: "PoolDB.Password", + path: "Pool.DB.Password", expectedValue: "pool_password", }, { - path: "PoolDB.Name", + path: "Pool.DB.Name", expectedValue: "pool_db", }, { - path: "PoolDB.Host", - expectedValue: "localhost", + path: "Pool.DB.Host", + expectedValue: "zkevm-pool-db", }, { - path: "PoolDB.Port", + path: "Pool.DB.Port", expectedValue: "5432", }, { - path: "PoolDB.EnableLog", + path: "Pool.DB.EnableLog", expectedValue: false, }, { - path: "PoolDB.MaxConns", + path: "Pool.DB.MaxConns", expectedValue: 200, }, { @@ -203,7 +348,15 @@ func Test_Defaults(t *testing.T) { }, { path: "RPC.Port", - expectedValue: int(8123), + expectedValue: int(8545), + }, + { + path: "RPC.ReadTimeout", + expectedValue: types.NewDuration(60 * time.Second), + }, + { + path: "RPC.WriteTimeout", + expectedValue: types.NewDuration(60 * time.Second), }, { path: "RPC.SequencerNodeURI", @@ -211,59 +364,87 @@ func Test_Defaults(t *testing.T) { }, { path: "RPC.MaxRequestsPerIPAndSecond", - expectedValue: float64(50), + expectedValue: float64(500), }, { - path: "RPC.BroadcastURI", - expectedValue: "127.0.0.1:61090", + path: "RPC.EnableL2SuggestedGasPricePolling", + expectedValue: true, }, { - path: "RPC.DefaultSenderAddress", - expectedValue: "0x1111111111111111111111111111111111111111", + path: "RPC.WebSockets.Enabled", + expectedValue: true, }, { - path: "RPC.DB.User", - expectedValue: "rpc_user", + path: "RPC.WebSockets.Host", + expectedValue: "0.0.0.0", }, { - path: "RPC.DB.Password", - expectedValue: "rpc_password", + path: "RPC.WebSockets.Port", + expectedValue: int(8546), }, { - path: "RPC.DB.Name", - expectedValue: "rpc_db", + path: "Executor.URI", + expectedValue: "zkevm-prover:50071", }, { - path: "RPC.DB.Host", - expectedValue: "localhost", + path: "Metrics.Host", + expectedValue: "0.0.0.0", }, { - path: "RPC.DB.Port", - expectedValue: "5432", + path: "Metrics.Port", + expectedValue: 9091, }, { - path: "RPC.DB.EnableLog", + path: "Metrics.Enabled", expectedValue: false, }, { - path: "RPC.DB.MaxConns", - expectedValue: 200, + path: "Aggregator.Host", + expectedValue: "0.0.0.0", }, { - path: "Executor.URI", - expectedValue: "127.0.0.1:50071", + path: "Aggregator.Port", + expectedValue: 50081, }, { - path: "BroadcastServer.Host", - expectedValue: "0.0.0.0", + path: "Aggregator.RetryTime", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "Aggregator.VerifyProofInterval", + expectedValue: types.NewDuration(90 * time.Second), }, { - path: "BroadcastServer.Port", - expectedValue: 61090, + path: "Aggregator.TxProfitabilityCheckerType", + expectedValue: aggregator.TxProfitabilityCheckerType(aggregator.ProfitabilityAcceptAll), + }, + { + path: "Aggregator.TxProfitabilityMinReward", + expectedValue: aggregator.TokenAmountWithDecimals{Int: big.NewInt(1100000000000000000)}, + }, + { + path: "Aggregator.ProofStatePollingInterval", + expectedValue: types.NewDuration(5 * time.Second), + }, + { + path: "Aggregator.CleanupLockedProofsInterval", + expectedValue: types.NewDuration(2 * time.Minute), + }, + { + path: "Aggregator.GeneratingProofCleanupThreshold", + expectedValue: "10m", }, } + file, err := os.CreateTemp("", "genesisConfig") + require.NoError(t, err) + defer func() { + require.NoError(t, os.Remove(file.Name())) + }() + require.NoError(t, os.WriteFile(file.Name(), []byte("{}"), 0600)) - ctx := cli.NewContext(cli.NewApp(), flag.NewFlagSet("", flag.PanicOnError), nil) + flagSet := flag.NewFlagSet("", flag.PanicOnError) + flagSet.String(config.FlagNetwork, "testnet", "") + ctx := cli.NewContext(cli.NewApp(), flagSet, nil) cfg, err := config.Load(ctx) if err != nil { t.Fatalf("Unexpected error loading default config: %v", err) @@ -291,3 +472,28 @@ func getValueFromStruct(path string, object interface{}) interface{} { } return v.Interface() } + +func TestEnvVarArrayDecoding(t *testing.T) { + file, err := os.CreateTemp("", "genesisConfig") + require.NoError(t, err) + defer func() { + require.NoError(t, os.Remove(file.Name())) + }() + require.NoError(t, os.WriteFile(file.Name(), []byte("{}"), 0600)) + flagSet := flag.NewFlagSet("", flag.PanicOnError) + flagSet.String(config.FlagNetwork, "testnet", "") + ctx := cli.NewContext(cli.NewApp(), flagSet, nil) + + os.Setenv("ZKEVM_NODE_LOG_OUTPUTS", "a,b,c") + defer func() { + os.Unsetenv("ZKEVM_NODE_LOG_OUTPUTS") + }() + + cfg, err := config.Load(ctx) + require.NoError(t, err) + + assert.Equal(t, 3, len(cfg.Log.Outputs)) + assert.Equal(t, "a", cfg.Log.Outputs[0]) + assert.Equal(t, "b", cfg.Log.Outputs[1]) + assert.Equal(t, "c", cfg.Log.Outputs[2]) +} diff --git a/config/default.go b/config/default.go index a2dd9d9322..18b7701b80 100644 --- a/config/default.go +++ b/config/default.go @@ -5,71 +5,70 @@ const DefaultValues = ` IsTrustedSequencer = false [Log] -Level = "debug" -Outputs = ["stdout"] +Environment = "development" # "production" or "development" +Level = "info" +Outputs = ["stderr"] [StateDB] User = "state_user" Password = "state_password" Name = "state_db" -Host = "localhost" +Host = "zkevm-state-db" Port = "5432" EnableLog = false MaxConns = 200 -[PoolDB] -User = "pool_user" -Password = "pool_password" -Name = "pool_db" -Host = "localhost" -Port = "5432" -EnableLog = false -MaxConns = 200 +[Pool] +IntervalToRefreshBlockedAddresses = "5m" +MaxTxBytesSize=100132 +MaxTxDataBytesSize=100000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "zkevm-pool-db" + Port = "5432" + EnableLog = false + MaxConns = 200 [Etherman] URL = "http://localhost:8545" -PrivateKeyPath = "./test/test.keystore" -PrivateKeyPassword = "testonly" +MultiGasProvider = false + [Etherman.Etherscan] + ApiKey = "" [EthTxManager] -MaxSendBatchTxRetries = 10 -MaxVerifyBatchTxRetries = 10 -FrequencyForResendingFailedSendBatches = "1s" -FrequencyForResendingFailedVerifyBatch = "1s" +FrequencyToMonitorTxs = "1s" WaitTxToBeMined = "2m" -PercentageToIncreaseGasPrice = 10 -PercentageToIncreaseGasLimit = 10 +ForcedGas = 0 [RPC] Host = "0.0.0.0" -Port = 8123 -MaxRequestsPerIPAndSecond = 50 +Port = 8545 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 500 SequencerNodeURI = "" -BroadcastURI = "127.0.0.1:61090" -DefaultSenderAddress = "0x1111111111111111111111111111111111111111" - [RPC.DB] - User = "rpc_user" - Password = "rpc_password" - Name = "rpc_db" - Host = "localhost" - Port = "5432" - EnableLog = false - MaxConns = 200 +EnableL2SuggestedGasPricePolling = true + [RPC.WebSockets] + Enabled = true + Host = "0.0.0.0" + Port = 8546 [Synchronizer] -SyncInterval = "0s" +SyncInterval = "1s" SyncChunkSize = 100 -TrustedSequencerURI = "" +TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc [Sequencer] -MaxSequenceSize = "2000000" WaitPeriodPoolIsEmpty = "1s" -WaitPeriodSendSequence = "15s" -LastBatchVirtualizationTimeMaxWaitPeriod = "300s" -WaitBlocksToUpdateGER = 10 -MaxTimeForBatchToBeOpen = "15s" BlocksAmountForTxsToBeDeleted = 100 FrequencyToCheckTxsForDelete = "12h" +MaxTxsPerBatch = 150 +MaxBatchBytesSize = 129848 MaxCumulativeGasUsed = 30000000 MaxKeccakHashes = 468 MaxPoseidonHashes = 279620 @@ -78,38 +77,71 @@ MaxMemAligns = 262144 MaxArithmetics = 262144 MaxBinaries = 262144 MaxSteps = 8388608 - [Sequencer.ProfitabilityChecker] - SendBatchesEvenWhenNotProfitable = "true" +WeightBatchBytesSize = 1 +WeightCumulativeGasUsed = 1 +WeightKeccakHashes = 1 +WeightPoseidonHashes = 1 +WeightPoseidonPaddings = 1 +WeightMemAligns = 1 +WeightArithmetics = 1 +WeightBinaries = 1 +WeightSteps = 1 +TxLifetimeCheckTimeout = "10m" +MaxTxLifetime = "3h" + [Sequencer.Finalizer] + GERDeadlineTimeout = "5s" + ForcedBatchDeadlineTimeout = "60s" + SleepDuration = "100ms" + ResourcePercentageToCloseBatch = 10 + GERFinalityNumberOfBlocks = 64 + ClosingSignalsManagerWaitForCheckingL1Timeout = "10s" + ClosingSignalsManagerWaitForCheckingGER = "10s" + ClosingSignalsManagerWaitForCheckingForcedBatches = "10s" + ForcedBatchesFinalityNumberOfBlocks = 64 + TimestampResolution = "10s" + [Sequencer.DBManager] + PoolRetrievalInterval = "500ms" + L2ReorgRetrievalInterval = "5s" + [Sequencer.Worker] + ResourceCostMultiplier = 1000 + +[SequenceSender] +WaitPeriodSendSequence = "5s" +LastBatchVirtualizationTimeMaxWaitPeriod = "5s" +MaxTxSizeForL1 = 131072 +SenderAddress = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +PrivateKeys = [{Path = "/pk/sequencer.keystore", Password = "testonly"}] [PriceGetter] Type = "default" DefaultPrice = "2000" [Aggregator] -IntervalFrequencyToGetProofGenerationState = "5s" -IntervalToConsolidateState = "3s" +Host = "0.0.0.0" +Port = 50081 +ForkId = 2 +RetryTime = "5s" +VerifyProofInterval = "90s" TxProfitabilityCheckerType = "acceptall" TxProfitabilityMinReward = "1.1" +ProofStatePollingInterval = "5s" +CleanupLockedProofsInterval = "2m" +GeneratingProofCleanupThreshold = "10m" -[GasPriceEstimator] -Type = "default" -DefaultGasPriceWei = 1000000000 - -[Prover] -ProverURI = "0.0.0.0:50051" - -[MTServer] -Host = "0.0.0.0" -Port = 50060 -StoreBackend = "PostgreSQL" +[L2GasPriceSuggester] +Type = "follower" +UpdatePeriod = "10s" +Factor = 0.15 +DefaultGasPriceWei = 2000000000 [MTClient] -URI = "127.0.0.1:50061" +URI = "zkevm-prover:50061" [Executor] -URI = "127.0.0.1:50071" +URI = "zkevm-prover:50071" -[BroadcastServer] +[Metrics] Host = "0.0.0.0" -Port = 61090 +Port = 9091 +Enabled = false ` diff --git a/config/environments/local/local.genesis.config.json b/config/environments/local/local.genesis.config.json new file mode 100644 index 0000000000..dc4a1e8bcb --- /dev/null +++ b/config/environments/local/local.genesis.config.json @@ -0,0 +1,102 @@ +{ + "l1Config" : { + "chainId": 1337, + "polygonZkEVMAddress": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "maticTokenAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "polygonZkEVMGlobalExitRootAddress": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" + }, + "root": "0xd88680f1b151dd67518f9aca85161424c0cac61df2f5424a3ddc04ea25adecc7", + "genesisBlockNumber": 65, + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0x4b2700570f8426A24EA85e0324611E527BdD55B8", + "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100e65780638da5cb5b146100fb578063e11ae6cb14610126578063f2fde38b1461013957600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610927565b610159565b005b6100886100983660046109c7565b6101cb565b3480156100a957600080fd5b506100bd6100b8366004610a1e565b61020d565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b50610088610220565b34801561010757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100bd565b610088610134366004610a40565b610234565b34801561014557600080fd5b50610088610154366004610a90565b61029b565b610161610357565b600061016e8585856103d8565b905061017a8183610537565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101d3610357565b6101de83838361057b565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b600061021983836105a9565b9392505050565b610228610357565b61023260006105b6565b565b61023c610357565b60006102498484846103d8565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b6102a3610357565b73ffffffffffffffffffffffffffffffffffffffff811661034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610354816105b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610342565b600083471015610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610342565b81516000036104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610342565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610342565b6060610219838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061062b565b60606105a1848484604051806060016040528060298152602001610b3d6029913961062b565b949350505050565b6000610219838330610744565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610342565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516106e69190610acf565b60006040518083038185875af1925050503d8060008114610723576040519150601f19603f3d011682016040523d82523d6000602084013e610728565b606091505b50915091506107398783838761076e565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156108045782516000036107fd5773ffffffffffffffffffffffffffffffffffffffff85163b6107fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610342565b50816105a1565b6105a183838151156108195781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103429190610aeb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261088d57600080fd5b813567ffffffffffffffff808211156108a8576108a861084d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108ee576108ee61084d565b8160405283815286602085880101111561090757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561093d57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561096357600080fd5b61096f8883890161087c565b9350606087013591508082111561098557600080fd5b506109928782880161087c565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff811681146109c257600080fd5b919050565b6000806000606084860312156109dc57600080fd5b6109e58461099e565b9250602084013567ffffffffffffffff811115610a0157600080fd5b610a0d8682870161087c565b925050604084013590509250925092565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600080600060608486031215610a5557600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a7a57600080fd5b610a868682870161087c565b9150509250925092565b600060208284031215610aa257600080fd5b6102198261099e565b60005b83811015610ac6578181015183820152602001610aae565b50506000910152565b60008251610ae1818460208701610aab565b9190910192915050565b6020815260008251806020840152610b0a816040850160208701610aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203e70ce334e8ec9d8d03e87415afd36dce4e82633bd277b08937095a6bd66367764736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0xf065BaE7C019ff5627E09ed48D4EeA317D211956", + "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b366004610608565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb36600461062c565b610269565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610694565b6102f7565b34801561014a57600080fd5b506100de61015936600461062c565b61038c565b34801561016a57600080fd5b506100de610179366004610608565b6103e8565b34801561018a57600080fd5b506100a0610199366004610608565b6104a4565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610788565b949350505050565b61025d6104f0565b6102676000610571565b565b6102716104f0565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156102db57600080fd5b505af11580156102ef573d6000803e3d6000fd5b505050505050565b6102ff6104f0565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061035590869086906004016107a5565b6000604051808303818588803b15801561036e57600080fd5b505af1158015610382573d6000803e3d6000fd5b5050505050505050565b6103946104f0565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102c1565b6103f06104f0565b73ffffffffffffffffffffffffffffffffffffffff8116610498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104a181610571565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161048f565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146104a157600080fd5b60006020828403121561061a57600080fd5b8135610625816105e6565b9392505050565b6000806040838503121561063f57600080fd5b823561064a816105e6565b9150602083013561065a816105e6565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156106a957600080fd5b83356106b4816105e6565b925060208401356106c4816105e6565b9150604084013567ffffffffffffffff808211156106e157600080fd5b818601915086601f8301126106f557600080fd5b81358181111561070757610707610665565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561074d5761074d610665565b8160405282815289602084870101111561076657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561079a57600080fd5b8151610625816105e6565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156107ef578581018301518582016060015282016107d3565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea2646970667358221220372a0e10eebea1b7fa43ae4c976994e6ed01d85eedc3637b83f01d3f06be442064736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0xf23919bb44BCa81aeAb4586BE71Ee3fd4E99B951", + "bytecode": "0x6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000639578063ee25560b1462000651578063fb570834146200068257600080fd5b8063be5831c714620005ae578063cd58657914620005ea578063d02103ca146200060157600080fd5b80639e34070f11620000be5780639e34070f146200050a578063aaa13cc2146200054f578063bab161bf146200057457600080fd5b8063647c576c146200048657806379e2cf9714620004ab57806381b1c17414620004c357600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf2146200034b5780633ae05047146200037a5780633e197043146200039257600080fd5b80632d2c9d9414620002765780632dfdf0b5146200029b578063318aee3d14620002c257600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200023a5780632cffd02e146200025157600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed620006a7565b005b348015620001fc57600080fd5b50620002146200020e366004620032db565b62000705565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001cc565b620001ed6200024b36600462003372565b620007a8565b3480156200025e57600080fd5b50620001ed6200027036600462003409565b620009d0565b3480156200028357600080fd5b50620001ed6200029536600462003409565b62000f74565b348015620002a857600080fd5b50620002b360535481565b604051908152602001620001cc565b348015620002cf57600080fd5b5062000319620002e1366004620034ef565b606b6020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001cc565b3480156200035857600080fd5b50606c54620002149073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200038757600080fd5b50620002b362001178565b3480156200039f57600080fd5b50620002b3620003b136600462003526565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200049357600080fd5b50620001ed620004a5366004620035b0565b6200125e565b348015620004b857600080fd5b50620001ed620014ad565b348015620004d057600080fd5b5062000214620004e236600462003600565b606a6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200051757600080fd5b50620001c06200052936600462003600565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200055c57600080fd5b50620002146200056e3660046200361a565b620014e7565b3480156200058157600080fd5b506068546200059890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620005bb57600080fd5b506068546200059890790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001ed620005fb366004620036ce565b620016d3565b3480156200060e57600080fd5b50606854620002149065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200064657600080fd5b50620001ed62001c37565b3480156200065e57600080fd5b50620002b36200067036600462003600565b60696020526000908152604090205481565b3480156200068f57600080fd5b50620001c0620006a136600462003770565b62001c93565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006f9576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362001d7c565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091206000908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007e6576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8681166101009092041614806200080c5750600263ffffffff861610155b1562000844576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163388883488886053546040516200089a9998979695949392919062003806565b60405180910390a1620009b8620009b26001606860019054906101000a900463ffffffff16338989348989604051620008d592919062003881565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b62001e10565b8215620009c957620009c962001f27565b5050505050565b60685460ff161562000a0e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000a258b8b8b8b8b8b8b8b8b8b8b600062001ffc565b73ffffffffffffffffffffffffffffffffffffffff861662000b01576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a7a9190620038e6565b60006040518083038185875af1925050503d806000811462000ab9576040519150601f19603f3d011682016040523d82523d6000602084013e62000abe565b606091505b505090508062000afa576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000efc565b60685463ffffffff61010090910481169088160362000b435762000b3d73ffffffffffffffffffffffffffffffffffffffff87168585620021ed565b62000efc565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e6e576000808062000c1886880188620039fb565b92509250925060008584848460405162000c329062003292565b62000c409392919062003abd565b8190604051809103906000f590508015801562000c61573d6000803e3d6000fd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b15801562000cd757600080fd5b505af115801562000cec573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e5c95949392919062003afa565b60405180910390a15050505062000ef9565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000edf57600080fd5b505af115801562000ef4573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000fb2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000fc98b8b8b8b8b8b8b8b8b8b8b600162001ffc565b60008473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000ffc949392919062003b42565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200107f9190620038e6565b60006040518083038185875af1925050503d8060008114620010be576040519150601f19603f3d011682016040523d82523d6000602084013e620010c3565b606091505b5050905080620010ff576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562001255578083901c600116600103620011e65760338160208110620011b257620011b262003b8a565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062001213565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806200124c9062003be8565b91505062001183565b50919392505050565b600054610100900460ff16158080156200127f5750600054600160ff909116105b806200129b5750303b1580156200129b575060005460ff166001145b6200132d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200138c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905562001443620022c3565b8015620014a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff16101562000703576200070362001f27565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200157d9062003292565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620015c8908d908d908d908d908d9060200162003c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001606929160200162003c64565b604051602081830303815290604052805190602001206040516020016200168f94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff161562001711576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200171b62002366565b60685463ffffffff888116610100909204161480620017415750600263ffffffff881610155b1562001779576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060608773ffffffffffffffffffffffffffffffffffffffff8816620017df57883414620017d5576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001ad9565b341562001818576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901562001908576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac90604401600060405180830381600087803b158015620018db57600080fd5b505af1158015620018f0573d6000803e3d6000fd5b50505050806020015194508060000151935062001ad7565b85156200191d576200191d898b8989620023db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200198b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b1919062003c97565b9050620019d773ffffffffffffffffffffffffffffffffffffffff8b1633308e620028f9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801562001a45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6b919062003c97565b905062001a79828262003cb1565b6068548c9850610100900463ffffffff169650935062001a998762002959565b62001aa48c62002a71565b62001aaf8d62002b7e565b60405160200162001ac39392919062003abd565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e868860535460405162001b1b98979695949392919062003cc7565b60405180910390a162001c0f620009b2600085878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b861562001c205762001c2062001f27565b5050505062001c2e60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c89576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362002c80565b600084815b602081101562001d6e57600163ffffffff8616821c8116900362001d0a5785816020811062001ccb5762001ccb62003b8a565b60200201358260405160200162001cec929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001d59565b8186826020811062001d205762001d2062003b8a565b602002013560405160200162001d40929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d658162003be8565b91505062001c98565b50821490505b949350505050565b60685460ff161562001dba576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b80600162001e216020600262003e79565b62001e2d919062003cb1565b6053541062001e68576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060536000815462001e7b9062003be8565b9182905550905060005b602081101562001f17578082901c60011660010362001ebd57826033826020811062001eb55762001eb562003b8a565b015550505050565b6033816020811062001ed35762001ed362003b8a565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001f0e9062003be8565b91505062001e85565b5062001f2262003e87565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001fad62001178565b6040518263ffffffff1660e01b815260040162001fcc91815260200190565b600060405180830381600087803b15801562001fe757600080fd5b505af1158015620014a7573d6000803e3d6000fd5b6200200d8b63ffffffff1662002d10565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915260009165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303816000875af1158015620020b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020d6919062003c97565b90508060000362002112576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff88811661010090920416146200215c576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606854600090610100900463ffffffff166200217a5750896200217d565b508a5b620021a66200219d848c8c8c8c8c8c8c604051620008d592919062003881565b8f8f8462001c93565b620021dd576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001f229084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002d75565b600054610100900460ff166200235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6200070362002e88565b600260015403620023d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001324565b6002600155565b6000620023ec600482848662003eb6565b620023f79162003ee2565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620026765760008080808080806200245a896004818d62003eb6565b81019062002469919062003f2b565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614620024dd576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146200252d576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002567576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620026229190620038e6565b6000604051808303816000865af19150503d806000811462002661576040519150601f19603f3d011682016040523d82523d6000602084013e62002666565b606091505b50505050505050505050620009c9565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c0000000000000000000000000000000000000000000000000000000014620026f2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080808080806200270a8a6004818e62003eb6565b81019062002719919062003f86565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146200278f576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87163014620027df576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f1691620028a39190620038e6565b6000604051808303816000865af19150503d8060008114620028e2576040519150601f19603f3d011682016040523d82523d6000602084013e620028e7565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014a79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002240565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde03000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff861691620029dd9190620038e6565b600060405180830381855afa9150503d806000811462002a1a576040519150601f19603f3d011682016040523d82523d6000602084013e62002a1f565b606091505b50915091508162002a66576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d74565b62001d748162002f21565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b41000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff86169162002af59190620038e6565b600060405180830381855afa9150503d806000811462002b32576040519150601f19603f3d011682016040523d82523d6000602084013e62002b37565b606091505b50915091508162002a66576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d74565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169162002c019190620038e6565b600060405180830381855afa9150503d806000811462002c3e576040519150601f19603f3d011682016040523d82523d6000602084013e62002c43565b606091505b509150915081801562002c57575080516020145b62002c6457601262001d74565b8080602001905181019062001d74919062004012565b60018055565b60685460ff1662002cbd576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009c9576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031119092919063ffffffff16565b80519091501562001f22578080602001905181019062002dfa919062004032565b62001f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162001324565b600054610100900460ff1662002c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6060604082511062002f435781806020019051810190620007a2919062004052565b8151602003620030d35760005b60208110801562002f9b575082818151811062002f715762002f7162003b8a565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002fb6578062002fad8162003be8565b91505062002f50565b8060000362002ffa57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562003018576200301862003891565b6040519080825280601f01601f19166020018201604052801562003043576020820181803683370190505b50905060005b82811015620030cb5784818151811062003067576200306762003b8a565b602001015160f81c60f81b82828151811062003087576200308762003b8a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620030c28162003be8565b91505062003049565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d748484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051620031489190620038e6565b60006040518083038185875af1925050503d806000811462003187576040519150601f19603f3d011682016040523d82523d6000602084013e6200318c565b606091505b50915091506200319f87838387620031aa565b979650505050505050565b60608315620032455782516000036200323d5773ffffffffffffffffffffffffffffffffffffffff85163b6200323d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162001324565b508162001d74565b62001d7483838151156200325c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620013249190620040d2565b611b6680620040e883390190565b803563ffffffff811681146200310c57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620032d857600080fd5b50565b60008060408385031215620032ef57600080fd5b620032fa83620032a0565b915060208301356200330c81620032b5565b809150509250929050565b8015158114620032d857600080fd5b60008083601f8401126200333957600080fd5b50813567ffffffffffffffff8111156200335257600080fd5b6020830191508360208285010111156200336b57600080fd5b9250929050565b6000806000806000608086880312156200338b57600080fd5b6200339686620032a0565b94506020860135620033a881620032b5565b93506040860135620033ba8162003317565b9250606086013567ffffffffffffffff811115620033d757600080fd5b620033e58882890162003326565b969995985093965092949392505050565b806104008101831015620007a257600080fd5b60008060008060008060008060008060006105208c8e0312156200342c57600080fd5b620034388d8d620033f6565b9a50620034496104008d01620032a0565b99506104208c013598506104408c013597506200346a6104608d01620032a0565b96506104808c01356200347d81620032b5565b95506200348e6104a08d01620032a0565b94506104c08c0135620034a181620032b5565b93506104e08c013592506105008c013567ffffffffffffffff811115620034c757600080fd5b620034d58e828f0162003326565b915080935050809150509295989b509295989b9093969950565b6000602082840312156200350257600080fd5b81356200350f81620032b5565b9392505050565b60ff81168114620032d857600080fd5b600080600080600080600060e0888a0312156200354257600080fd5b87356200354f8162003516565b96506200355f60208901620032a0565b955060408801356200357181620032b5565b94506200358160608901620032a0565b935060808801356200359381620032b5565b9699959850939692959460a0840135945060c09093013592915050565b600080600060608486031215620035c657600080fd5b620035d184620032a0565b92506020840135620035e381620032b5565b91506040840135620035f581620032b5565b809150509250925092565b6000602082840312156200361357600080fd5b5035919050565b600080600080600080600060a0888a0312156200363657600080fd5b6200364188620032a0565b965060208801356200365381620032b5565b9550604088013567ffffffffffffffff808211156200367157600080fd5b6200367f8b838c0162003326565b909750955060608a01359150808211156200369957600080fd5b50620036a88a828b0162003326565b9094509250506080880135620036be8162003516565b8091505092959891949750929550565b600080600080600080600060c0888a031215620036ea57600080fd5b620036f588620032a0565b965060208801356200370781620032b5565b95506040880135945060608801356200372081620032b5565b93506080880135620037328162003317565b925060a088013567ffffffffffffffff8111156200374f57600080fd5b6200375d8a828b0162003326565b989b979a50959850939692959293505050565b60008060008061046085870312156200378857600080fd5b843593506200379b8660208701620033f6565b9250620037ac6104208601620032a0565b939692955092936104400135925050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620038678285018789620037bd565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811015620038dd578181015183820152602001620038c3565b50506000910152565b60008251620038fa818460208701620038c0565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200394e576200394e62003891565b604052919050565b600067ffffffffffffffff82111562003973576200397362003891565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620039b157600080fd5b8135620039c8620039c28262003956565b62003904565b818152846020838601011115620039de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562003a1157600080fd5b833567ffffffffffffffff8082111562003a2a57600080fd5b62003a38878388016200399f565b9450602086013591508082111562003a4f57600080fd5b5062003a5e868287016200399f565b9250506040840135620035f58162003516565b6000815180845262003a8b816020860160208601620038c0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062003ad2606083018662003a71565b828103602084015262003ae6818662003a71565b91505060ff83166040830152949350505050565b63ffffffff86168152600073ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200319f608083018486620037bd565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff8416602082015260606040820152600062003b80606083018486620037bd565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003c1c5762003c1c62003bb9565b5060010190565b60608152600062003c39606083018789620037bd565b828103602084015262003c4e818688620037bd565b91505060ff831660408301529695505050505050565b6000835162003c78818460208801620038c0565b83519083019062003c8e818360208801620038c0565b01949350505050565b60006020828403121562003caa57600080fd5b5051919050565b81810381811115620007a257620007a262003bb9565b600061010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003d278285018762003a71565b925080851660e085015250509998505050505050505050565b600181815b8085111562003d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d835762003d8362003bb9565b8085161562003d9157918102915b93841c939080029062003d45565b509250929050565b60008262003db857506001620007a2565b8162003dc757506000620007a2565b816001811462003de0576002811462003deb5762003e0b565b6001915050620007a2565b60ff84111562003dff5762003dff62003bb9565b50506001821b620007a2565b5060208310610133831016604e8410600b841016171562003e30575081810a620007a2565b62003e3c838362003d40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003e715762003e7162003bb9565b029392505050565b60006200350f838362003da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000808585111562003ec757600080fd5b8386111562003ed557600080fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003f235780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a03121562003f4757600080fd5b873562003f5481620032b5565b9650602088013562003f6681620032b5565b955060408801359450606088013593506080880135620035938162003516565b600080600080600080600080610100898b03121562003fa457600080fd5b883562003fb181620032b5565b9750602089013562003fc381620032b5565b96506040890135955060608901359450608089013562003fe38162003317565b935060a089013562003ff58162003516565b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156200402557600080fd5b81516200350f8162003516565b6000602082840312156200404557600080fd5b81516200350f8162003317565b6000602082840312156200406557600080fd5b815167ffffffffffffffff8111156200407d57600080fd5b8201601f810184136200408f57600080fd5b8051620040a0620039c28262003956565b818152856020838501011115620040b657600080fd5b620040c9826020830160208601620038c0565b95945050505050565b6020815260006200350f602083018462003a7156fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220d9b3ca7b13ec80ac58634ddf0ecebe71e209a71f532614949b9e720413f50c8364736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "200000000000000000000000000", + "nonce": "1", + "address": "0xff0EE8ea08cEf5cb4322777F5CC3E8A584B8A4A0", + "bytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461088b565b610135565b61006b6100a33660046108a6565b61017f565b3480156100b457600080fd5b506100bd6101f3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461088b565b610231565b34801561011257600080fd5b506100bd61025e565b6101236102d4565b61013361012e6103ab565b6103b5565b565b61013d6103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481604051806020016040528060008152506000610419565b50565b61017461011b565b6101876103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101eb576101e68383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610419915050565b505050565b6101e661011b565b60006101fd6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103ab565b905090565b61022e61011b565b90565b6102396103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481610444565b60006102686103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103d9565b60606102b183836040518060600160405280602781526020016109bb602791396104a5565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6102dc6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061022161052a565b3660008037600080366000845af43d6000803e8080156103d4573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b61042283610552565b60008251118061042f5750805b156101e65761043e838361028c565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61046d6103d9565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16101748161059f565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516104cf919061094d565b600060405180830381855af49150503d806000811461050a576040519150601f19603f3d011682016040523d82523d6000602084013e61050f565b606091505b5091509150610520868383876106ab565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103fd565b61055b81610753565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a2565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6060831561074157825160000361073a5773ffffffffffffffffffffffffffffffffffffffff85163b61073a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a2565b508161074b565b61074b838361081e565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81163b6107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016103a2565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610665565b81511561082e5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a29190610969565b803573ffffffffffffffffffffffffffffffffffffffff8116811461088657600080fd5b919050565b60006020828403121561089d57600080fd5b6102b182610862565b6000806000604084860312156108bb57600080fd5b6108c484610862565b9250602084013567ffffffffffffffff808211156108e157600080fd5b818601915086601f8301126108f557600080fd5b81358181111561090457600080fd5b87602082850101111561091657600080fd5b6020830194508093505050509250925092565b60005b8381101561094457818101518382015260200161092c565b50506000910152565b6000825161095f818460208701610929565b9190910192915050565b6020815260008251806020840152610988816040850160208701610929565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a1af0d6cb4f1e31496a4c5c1448913bce4bd6ad3a39e47c6f7190c114d6f9bf464736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000068": "0x00000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa0000000100", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000f065bae7c019ff5627e09ed48d4eea317d211956", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000f23919bb44bca81aeab4586be71ee3fd4e99b951" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610162565b60006020819052908152604090205481565b6100a061009b366004610162565b6100ee565b005b6100c97f000000000000000000000000ff0ee8ea08cef5cb4322777f5cc3e8a584b8a4a081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff0ee8ea08cef5cb4322777f5cc3e8a584b8a4a0161461015d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b60006020828403121561017457600080fd5b503591905056fea2646970667358221220a187fc278346c1b61c449ea3641002b6eac2bda3351a122a12c35099f933696864736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106ca565b610118565b61005b6100933660046106e5565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106ca565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103f1565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107e460279139610445565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb610519565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b83610541565b6040516001600160a01b038416907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000825111806103dc5750805b156101c3576103eb8383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a61035f565b604080516001600160a01b03928316815291841660208301520160405180910390a1610154816105e9565b6060833b6104a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b0316856040516104bf9190610794565b600060405180830381855af49150503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b509150915061050f828286610675565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b803b6105a55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b03811661064e5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036105c8565b60608315610684575081610285565b8251156106945782518084602001fd5b8160405162461bcd60e51b815260040161032891906107b0565b80356001600160a01b03811681146106c557600080fd5b919050565b6000602082840312156106dc57600080fd5b610285826106ae565b6000806000604084860312156106fa57600080fd5b610703846106ae565b9250602084013567ffffffffffffffff8082111561072057600080fd5b818601915086601f83011261073457600080fd5b81358181111561074357600080fd5b87602082850101111561075557600080fd5b6020830194508093505050509250925092565b60005b8381101561078357818101518382015260200161076b565b838111156103eb5750506000910152565b600082516107a6818460208701610768565b9190910192915050565b60208152600082518060208401526107cf816040850160208701610768565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204675187caf3a43285d9a2c1844a981e977bd52a85ff073e7fc649f73847d70a464736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000f065bae7c019ff5627e09ed48d4eea317d211956", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c9" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "bytecode": "0x6080604052600436106101c65760003560e01c806364d62353116100f7578063b1c5f42711610095578063d547741f11610064578063d547741f14610661578063e38335e514610681578063f23a6e6114610694578063f27a0c92146106d957600080fd5b8063b1c5f427146105af578063bc197c81146105cf578063c4d252f514610614578063d45c44351461063457600080fd5b80638f61f4f5116100d15780638f61f4f5146104e157806391d1485414610515578063a217fddf14610566578063b08e51c01461057b57600080fd5b806364d62353146104815780638065657f146104a15780638f2a0bb0146104c157600080fd5b8063248a9ca31161016457806331d507501161013e57806331d50750146103c857806336568abe146103e85780633a6aae7214610408578063584b153e1461046157600080fd5b8063248a9ca3146103475780632ab0f529146103775780632f2ff15d146103a857600080fd5b80630d3cf6fc116101a05780630d3cf6fc1461026b578063134008d31461029f57806313bc9f20146102b2578063150b7a02146102d257600080fd5b806301d5062a146101d257806301ffc9a7146101f457806307bd02651461022957600080fd5b366101cd57005b600080fd5b3480156101de57600080fd5b506101f26101ed366004611c52565b6106ee565b005b34801561020057600080fd5b5061021461020f366004611cc7565b610783565b60405190151581526020015b60405180910390f35b34801561023557600080fd5b5061025d7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610220565b34801561027757600080fd5b5061025d7f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101f26102ad366004611d09565b6107df565b3480156102be57600080fd5b506102146102cd366004611d75565b6108d7565b3480156102de57600080fd5b506103166102ed366004611e9a565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610220565b34801561035357600080fd5b5061025d610362366004611d75565b60009081526020819052604090206001015490565b34801561038357600080fd5b50610214610392366004611d75565b6000908152600160208190526040909120541490565b3480156103b457600080fd5b506101f26103c3366004611f02565b6108fd565b3480156103d457600080fd5b506102146103e3366004611d75565b610927565b3480156103f457600080fd5b506101f2610403366004611f02565b610940565b34801561041457600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610220565b34801561046d57600080fd5b5061021461047c366004611d75565b6109f8565b34801561048d57600080fd5b506101f261049c366004611d75565b610a0e565b3480156104ad57600080fd5b5061025d6104bc366004611d09565b610ade565b3480156104cd57600080fd5b506101f26104dc366004611f73565b610b1d565b3480156104ed57600080fd5b5061025d7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561052157600080fd5b50610214610530366004611f02565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561057257600080fd5b5061025d600081565b34801561058757600080fd5b5061025d7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156105bb57600080fd5b5061025d6105ca366004612025565b610d4f565b3480156105db57600080fd5b506103166105ea36600461214e565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b34801561062057600080fd5b506101f261062f366004611d75565b610d94565b34801561064057600080fd5b5061025d61064f366004611d75565b60009081526001602052604090205490565b34801561066d57600080fd5b506101f261067c366004611f02565b610e8f565b6101f261068f366004612025565b610eb4565b3480156106a057600080fd5b506103166106af3660046121f8565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106e557600080fd5b5061025d611161565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161071881611244565b6000610728898989898989610ade565b90506107348184611251565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a604051610770969594939291906122a6565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107d957506107d98261139e565b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661085c5761085c8133611435565b600061086c888888888888610ade565b905061087881856114ed565b6108848888888861162a565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516108bc94939291906122f1565b60405180910390a36108cd8161172e565b5050505050505050565b6000818152600160205260408120546001811180156108f65750428111155b9392505050565b60008281526020819052604090206001015461091881611244565b61092283836117d7565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109f482826118c7565b5050565b6000818152600160208190526040822054610939565b333014610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109e1565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610afb969594939291906122a6565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b4781611244565b888714610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b888514610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b6000610c778b8b8b8b8b8b8b8b610d4f565b9050610c838184611251565b60005b8a811015610d415780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610cc357610cc3612331565b9050602002016020810190610cd89190612360565b8d8d86818110610cea57610cea612331565b905060200201358c8c87818110610d0357610d03612331565b9050602002810190610d15919061237b565b8c8b604051610d29969594939291906122a6565b60405180910390a3610d3a8161240f565b9050610c86565b505050505050505050505050565b60008888888888888888604051602001610d709897969594939291906124f7565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610dbe81611244565b610dc7826109f8565b610e53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109e1565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610eaa81611244565b61092283836118c7565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610f3157610f318133611435565b878614610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b87841461104f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b60006110618a8a8a8a8a8a8a8a610d4f565b905061106d81856114ed565b60005b8981101561114b5760008b8b8381811061108c5761108c612331565b90506020020160208101906110a19190612360565b905060008a8a848181106110b7576110b7612331565b9050602002013590503660008a8a868181106110d5576110d5612331565b90506020028101906110e7919061237b565b915091506110f78484848461162a565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161112e94939291906122f1565b60405180910390a350505050806111449061240f565b9050611070565b506111558161172e565b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580159061123257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123291906125be565b1561123d5750600090565b5060025490565b61124e8133611435565b50565b61125a82610927565b156112e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109e1565b6112ef611161565b81101561137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109e1565b61138881426125e0565b6000928352600160205260409092209190915550565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107d957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107d9565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f4576114738161197e565b61147e83602061199d565b60405160200161148f929190612617565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109e191600401612698565b6114f6826108d7565b611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b80158061159e5750600081815260016020819052604090912054145b6109f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109e1565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516116549291906126e9565b60006040518083038185875af1925050503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b5050905080611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109e1565b5050505050565b611737816108d7565b6117c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556118693390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107d973ffffffffffffffffffffffffffffffffffffffff831660145b606060006119ac8360026126f9565b6119b79060026125e0565b67ffffffffffffffff8111156119cf576119cf611d8e565b6040519080825280601f01601f1916602001820160405280156119f9576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611a3057611a30612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a9357611a93612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000611acf8460026126f9565b611ada9060016125e0565b90505b6001811115611b77577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611b1b57611b1b612331565b1a60f81b828281518110611b3157611b31612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93611b7081612710565b9050611add565b5083156108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109e1565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c0457600080fd5b919050565b60008083601f840112611c1b57600080fd5b50813567ffffffffffffffff811115611c3357600080fd5b602083019150836020828501011115611c4b57600080fd5b9250929050565b600080600080600080600060c0888a031215611c6d57600080fd5b611c7688611be0565b965060208801359550604088013567ffffffffffffffff811115611c9957600080fd5b611ca58a828b01611c09565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611cd957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108f657600080fd5b60008060008060008060a08789031215611d2257600080fd5b611d2b87611be0565b955060208701359450604087013567ffffffffffffffff811115611d4e57600080fd5b611d5a89828a01611c09565b979a9699509760608101359660809091013595509350505050565b600060208284031215611d8757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e0457611e04611d8e565b604052919050565b600082601f830112611e1d57600080fd5b813567ffffffffffffffff811115611e3757611e37611d8e565b611e6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611dbd565b818152846020838601011115611e7d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611eb057600080fd5b611eb985611be0565b9350611ec760208601611be0565b925060408501359150606085013567ffffffffffffffff811115611eea57600080fd5b611ef687828801611e0c565b91505092959194509250565b60008060408385031215611f1557600080fd5b82359150611f2560208401611be0565b90509250929050565b60008083601f840112611f4057600080fd5b50813567ffffffffffffffff811115611f5857600080fd5b6020830191508360208260051b8501011115611c4b57600080fd5b600080600080600080600080600060c08a8c031215611f9157600080fd5b893567ffffffffffffffff80821115611fa957600080fd5b611fb58d838e01611f2e565b909b50995060208c0135915080821115611fce57600080fd5b611fda8d838e01611f2e565b909950975060408c0135915080821115611ff357600080fd5b506120008c828d01611f2e565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b03121561204157600080fd5b883567ffffffffffffffff8082111561205957600080fd5b6120658c838d01611f2e565b909a50985060208b013591508082111561207e57600080fd5b61208a8c838d01611f2e565b909850965060408b01359150808211156120a357600080fd5b506120b08b828c01611f2e565b999c989b509699959896976060870135966080013595509350505050565b600082601f8301126120df57600080fd5b8135602067ffffffffffffffff8211156120fb576120fb611d8e565b8160051b61210a828201611dbd565b928352848101820192828101908785111561212457600080fd5b83870192505b848310156121435782358252918301919083019061212a565b979650505050505050565b600080600080600060a0868803121561216657600080fd5b61216f86611be0565b945061217d60208701611be0565b9350604086013567ffffffffffffffff8082111561219a57600080fd5b6121a689838a016120ce565b945060608801359150808211156121bc57600080fd5b6121c889838a016120ce565b935060808801359150808211156121de57600080fd5b506121eb88828901611e0c565b9150509295509295909350565b600080600080600060a0868803121561221057600080fd5b61221986611be0565b945061222760208701611be0565b93506040860135925060608601359150608086013567ffffffffffffffff81111561225157600080fd5b6121eb88828901611e0c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a0604082015260006122dc60a08301868861225d565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061232760608301848661225d565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561237257600080fd5b6108f682611be0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126123b057600080fd5b83018035915067ffffffffffffffff8211156123cb57600080fd5b602001915036819003821315611c4b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612440576124406123e0565b5060010190565b81835260006020808501808196508560051b810191508460005b878110156124ea57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126124a057600080fd5b8701858101903567ffffffffffffffff8111156124bc57600080fd5b8036038213156124cb57600080fd5b6124d686828461225d565b9a87019a9550505090840190600101612461565b5091979650505050505050565b60a0808252810188905260008960c08301825b8b8110156125455773ffffffffffffffffffffffffffffffffffffffff61253084611be0565b1682526020928301929091019060010161250a565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89111561257e57600080fd5b8860051b9150818a602083013701828103602090810160408501526125a69082018789612447565b60608401959095525050608001529695505050505050565b6000602082840312156125d057600080fd5b815180151581146108f657600080fd5b808201808211156107d9576107d96123e0565b60005b8381101561260e5781810151838201526020016125f6565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161264f8160178501602088016125f3565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161268c8160288401602088016125f3565b01602801949350505050565b60208152600082518060208401526126b78160408501602087016125f3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b8183823760009101908152919050565b80820281158282048414176107d9576107d96123e0565b60008161271f5761271f6123e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212206416c4e08f97752b4bb06159524dac058d3dccd8775e57ef1b01505751ebf7af64736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0xaedcc9e7897c0d335bdc5d92fe3a8b4f23727fe558cd1c19f332b28716a30559": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xf5e61edb9c9cc6bfbae4463e9a2b1dd6ac3b44ddef38f18016e56ba0363910d9": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x60b9d94c75b7b3f721925089391e4644cd890cb5e6466f9596dfbd2c54e0b280": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x4b63b79f1e338a49559dcd3193ac9eecc50d0f275d24e97cc8c319e5a31a8bd0": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x800d5dfe4bba53eedee06cd4546a27da8de00f12db83f56062976d4493fda899": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x20E7077d25fe79C5F6c2D3ae4905E96aA7C89c13" + }, + { + "accountName": "deployer", + "balance": "100000000000000000000000", + "nonce": "8", + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ] + } \ No newline at end of file diff --git a/config/environments/local/local.node.config.toml b/config/environments/local/local.node.config.toml new file mode 100644 index 0000000000..d6e9eb91bc --- /dev/null +++ b/config/environments/local/local.node.config.toml @@ -0,0 +1,141 @@ +IsTrustedSequencer = false + +[Log] +Environment = "development" # "production" or "development" +Level = "debug" +Outputs = ["stderr"] + +[StateDB] +User = "state_user" +Password = "state_password" +Name = "state_db" +Host = "zkevm-state-db" +Port = "5432" +EnableLog = false +MaxConns = 200 + +[Pool] +IntervalToRefreshBlockedAddresses = "5m" +MaxTxBytesSize=100132 +MaxTxDataBytesSize=100000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "zkevm-pool-db" + Port = "5432" + EnableLog = false + MaxConns = 200 + +[Etherman] +URL = "http://your.L1node.url" +MultiGasProvider = false + [Etherman.Etherscan] + ApiKey = "" + +[RPC] +Host = "0.0.0.0" +Port = 8545 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 5000 +SequencerNodeURI = "https://internal.zkevm-test.net:2083/" +EnableL2SuggestedGasPricePolling = true + [RPC.WebSockets] + Enabled = true + Port = 8546 + +[Synchronizer] +SyncInterval = "1s" +SyncChunkSize = 100 +TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc + +[Sequencer] +WaitPeriodPoolIsEmpty = "1s" +BlocksAmountForTxsToBeDeleted = 100 +FrequencyToCheckTxsForDelete = "12h" +MaxTxsPerBatch = 150 +MaxBatchBytesSize = 129848 +MaxCumulativeGasUsed = 30000000 +MaxKeccakHashes = 468 +MaxPoseidonHashes = 279620 +MaxPoseidonPaddings = 149796 +MaxMemAligns = 262144 +MaxArithmetics = 262144 +MaxBinaries = 262144 +MaxSteps = 8388608 +WeightBatchBytesSize = 1 +WeightCumulativeGasUsed = 1 +WeightKeccakHashes = 1 +WeightPoseidonHashes = 1 +WeightPoseidonPaddings = 1 +WeightMemAligns = 1 +WeightArithmetics = 1 +WeightBinaries = 1 +WeightSteps = 1 +TxLifetimeCheckTimeout = "10m" +MaxTxLifetime = "3h" + [Sequencer.Finalizer] + GERDeadlineTimeout = "5s" + ForcedBatchDeadlineTimeout = "60s" + SleepDuration = "100ms" + ResourcePercentageToCloseBatch = 10 + GERFinalityNumberOfBlocks = 0 + ClosingSignalsManagerWaitForCheckingL1Timeout = "10s" + ClosingSignalsManagerWaitForCheckingGER = "10s" + ClosingSignalsManagerWaitForCheckingForcedBatches = "10s" + ForcedBatchesFinalityNumberOfBlocks = 64 + TimestampResolution = "10s" + [Sequencer.DBManager] + PoolRetrievalInterval = "500ms" + L2ReorgRetrievalInterval = "5s" + [Sequencer.Worker] + ResourceCostMultiplier = 1000 + +[SequenceSender] +WaitPeriodSendSequence = "5s" +LastBatchVirtualizationTimeMaxWaitPeriod = "5s" +MaxTxSizeForL1 = 131072 +SenderAddress = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +PrivateKeys = [{Path = "/pk/sequencer.keystore", Password = "testonly"}] + +[Aggregator] +Host = "0.0.0.0" +Port = 50081 +ForkId = 2 +RetryTime = "5s" +VerifyProofInterval = "30s" +TxProfitabilityCheckerType = "acceptall" +TxProfitabilityMinReward = "1.1" +ProofStatePollingInterval = "5s" +SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +CleanupLockedProofsInterval = "2m" +GeneratingProofCleanupThreshold = "10m" + +[EthTxManager] +ForcedGas = 0 +PrivateKeys = [ + {Path = "/pk/sequencer.keystore", Password = "testonly"}, + {Path = "/pk/aggregator.keystore", Password = "testonly"} +] + +[L2GasPriceSuggester] +Type = "default" +DefaultGasPriceWei = 1000000000 + +[MTClient] +URI = "zkevm-prover:50061" + +[Executor] +URI = "zkevm-prover:50071" + +[Metrics] +Host = "0.0.0.0" +Port = 9091 +Enabled = false +ProfilingHost = "0.0.0.0" +ProfilingPort = 6060 +ProfilingEnabled = false diff --git a/config/environments/mainnet/example.env b/config/environments/mainnet/example.env new file mode 100644 index 0000000000..95557a442c --- /dev/null +++ b/config/environments/mainnet/example.env @@ -0,0 +1,9 @@ +ZKEVM_NETWORK = "mainnet" +# URL of a JSON RPC for Ethereum mainnet +ZKEVM_NODE_ETHERMAN_URL = "http://your.L1node.url" +# PATH WHERE THE STATEDB POSTGRES CONTAINER WILL STORE PERSISTENT DATA +ZKEVM_NODE_STATEDB_DATA_DIR = "/path/to/persistent/data/statedb" +# PATH WHERE THE POOLDB POSTGRES CONTAINER WILL STORE PERSISTENT DATA +ZKEVM_NODE_POOLDB_DATA_DIR = "/path/to/persistent/data/pooldb" +# OPTIONAL, UNCOMENT IF YOU WANT TO DO ADVANCED CONFIG +# ZKEVM_ADVANCED_CONFIG_DIR = "/should/be/same/path/as/ZKEVM_CONFIG_DIR" \ No newline at end of file diff --git a/config/environments/mainnet/postgresql.conf b/config/environments/mainnet/postgresql.conf new file mode 100644 index 0000000000..51dff68697 --- /dev/null +++ b/config/environments/mainnet/postgresql.conf @@ -0,0 +1,815 @@ +# ----------------------------- +# PostgreSQL configuration file +# ----------------------------- +# +# This file consists of lines of the form: +# +# name = value +# +# (The "=" is optional.) Whitespace may be used. Comments are introduced with +# "#" anywhere on a line. The complete list of parameter names and allowed +# values can be found in the PostgreSQL documentation. +# +# The commented-out settings shown in this file represent the default values. +# Re-commenting a setting is NOT sufficient to revert it to the default value; +# you need to reload the server. +# +# This file is read on server startup and when the server receives a SIGHUP +# signal. If you edit the file on a running system, you have to SIGHUP the +# server for the changes to take effect, run "pg_ctl reload", or execute +# "SELECT pg_reload_conf()". Some parameters, which are marked below, +# require a server shutdown and restart to take effect. +# +# Any parameter can also be given as a command-line option to the server, e.g., +# "postgres -c log_connections=on". Some parameters can be changed at run time +# with the "SET" SQL command. +# +# Memory units: B = bytes Time units: us = microseconds +# kB = kilobytes ms = milliseconds +# MB = megabytes s = seconds +# GB = gigabytes min = minutes +# TB = terabytes h = hours +# d = days + + +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +# The default values of these variables are driven from the -D command-line +# option or PGDATA environment variable, represented here as ConfigDir. + +#data_directory = 'ConfigDir' # use data in another directory + # (change requires restart) +#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file + # (change requires restart) +#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file + # (change requires restart) + +# If external_pid_file is not explicitly set, no extra PID file is written. +#external_pid_file = '' # write an extra PID file + # (change requires restart) + + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' + # comma-separated list of addresses; + # defaults to 'localhost'; use '*' for all + # (change requires restart) +#port = 5432 # (change requires restart) +max_connections = 100 # (change requires restart) +#superuser_reserved_connections = 3 # (change requires restart) +#unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories + # (change requires restart) +#unix_socket_group = '' # (change requires restart) +#unix_socket_permissions = 0777 # begin with 0 to use octal notation + # (change requires restart) +#bonjour = off # advertise server via Bonjour + # (change requires restart) +#bonjour_name = '' # defaults to the computer name + # (change requires restart) + +# - TCP settings - +# see "man tcp" for details + +#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; + # 0 selects the system default +#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; + # 0 selects the system default +#tcp_keepalives_count = 0 # TCP_KEEPCNT; + # 0 selects the system default +#tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds; + # 0 selects the system default + +#client_connection_check_interval = 0 # time between checks for client + # disconnection while running queries; + # 0 for never + +# - Authentication - + +#authentication_timeout = 1min # 1s-600s +#password_encryption = scram-sha-256 # scram-sha-256 or md5 +#db_user_namespace = off + +# GSSAPI using Kerberos +#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab' +#krb_caseins_users = off + +# - SSL - + +#ssl = off +#ssl_ca_file = '' +#ssl_cert_file = 'server.crt' +#ssl_crl_file = '' +#ssl_crl_dir = '' +#ssl_key_file = 'server.key' +#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers +#ssl_prefer_server_ciphers = on +#ssl_ecdh_curve = 'prime256v1' +#ssl_min_protocol_version = 'TLSv1.2' +#ssl_max_protocol_version = '' +#ssl_dh_params_file = '' +#ssl_passphrase_command = '' +#ssl_passphrase_command_supports_reload = off + + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +shared_buffers = 8GB # min 128kB + # (change requires restart) +#huge_pages = try # on, off, or try + # (change requires restart) +#huge_page_size = 0 # zero for system default + # (change requires restart) +temp_buffers = 64MB # min 800kB +#max_prepared_transactions = 0 # zero disables the feature + # (change requires restart) +# Caution: it is not advisable to set max_prepared_transactions nonzero unless +# you actively intend to use prepared transactions. +work_mem = 104857kB # min 64kB +#hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem +maintenance_work_mem = 2GB # min 1MB +#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem +#logical_decoding_work_mem = 64MB # min 64kB +#max_stack_depth = 2MB # min 100kB +#shared_memory_type = mmap # the default is the first option + # supported by the operating system: + # mmap + # sysv + # windows + # (change requires restart) +dynamic_shared_memory_type = posix # the default is usually the first option + # supported by the operating system: + # posix + # sysv + # windows + # mmap + # (change requires restart) +#min_dynamic_shared_memory = 0MB # (change requires restart) + +# - Disk - + +#temp_file_limit = -1 # limits per-process temp file space + # in kilobytes, or -1 for no limit + +# - Kernel Resources - + +#max_files_per_process = 1000 # min 64 + # (change requires restart) + +# - Cost-Based Vacuum Delay - + +#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) +#vacuum_cost_page_hit = 1 # 0-10000 credits +#vacuum_cost_page_miss = 2 # 0-10000 credits +#vacuum_cost_page_dirty = 20 # 0-10000 credits +#vacuum_cost_limit = 200 # 1-10000 credits + +# - Background Writer - + +#bgwriter_delay = 200ms # 10-10000ms between rounds +#bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables +#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round +#bgwriter_flush_after = 512kB # measured in pages, 0 disables + +# - Asynchronous Behavior - + +#backend_flush_after = 0 # measured in pages, 0 disables +effective_io_concurrency = 300 # 1-1000; 0 disables prefetching +#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching +max_worker_processes = 16 # (change requires restart) +max_parallel_workers_per_gather = 4 # taken from max_parallel_workers +max_parallel_maintenance_workers = 4 # taken from max_parallel_workers +max_parallel_workers = 16 # maximum number of max_worker_processes that + # can be used in parallel operations +#parallel_leader_participation = on +#old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate + # (change requires restart) + + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Settings - + +#wal_level = replica # minimal, replica, or logical + # (change requires restart) +#fsync = on # flush data to disk for crash safety + # (turning this off can cause + # unrecoverable data corruption) +#synchronous_commit = on # synchronization level; + # off, local, remote_write, remote_apply, or on +#wal_sync_method = fsync # the default is the first option + # supported by the operating system: + # open_datasync + # fdatasync (default on Linux and FreeBSD) + # fsync + # fsync_writethrough + # open_sync +#full_page_writes = on # recover from partial page writes +#wal_log_hints = off # also do full page writes of non-critical updates + # (change requires restart) +#wal_compression = off # enables compression of full-page writes; + # off, pglz, lz4, zstd, or on +#wal_init_zero = on # zero-fill new WAL files +#wal_recycle = on # recycle WAL files +wal_buffers = 16MB # min 32kB, -1 sets based on shared_buffers + # (change requires restart) +#wal_writer_delay = 200ms # 1-10000 milliseconds +#wal_writer_flush_after = 1MB # measured in pages, 0 disables +#wal_skip_threshold = 2MB + +#commit_delay = 0 # range 0-100000, in microseconds +#commit_siblings = 5 # range 1-1000 + +# - Checkpoints - + +#checkpoint_timeout = 5min # range 30s-1d +checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0 +#checkpoint_flush_after = 256kB # measured in pages, 0 disables +#checkpoint_warning = 30s # 0 disables +max_wal_size = 8GB +min_wal_size = 2GB + +# - Prefetching during recovery - + +#recovery_prefetch = try # prefetch pages referenced in the WAL? +#wal_decode_buffer_size = 512kB # lookahead window used for prefetching + # (change requires restart) + +# - Archiving - + +#archive_mode = off # enables archiving; off, on, or always + # (change requires restart) +#archive_library = '' # library to use to archive a logfile segment + # (empty string indicates archive_command should + # be used) +#archive_command = '' # command to use to archive a logfile segment + # placeholders: %p = path of file to archive + # %f = file name only + # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' +#archive_timeout = 0 # force a logfile segment switch after this + # number of seconds; 0 disables + +# - Archive Recovery - + +# These are only used in recovery mode. + +#restore_command = '' # command to use to restore an archived logfile segment + # placeholders: %p = path of file to restore + # %f = file name only + # e.g. 'cp /mnt/server/archivedir/%f %p' +#archive_cleanup_command = '' # command to execute at every restartpoint +#recovery_end_command = '' # command to execute at completion of recovery + +# - Recovery Target - + +# Set these only when performing a targeted recovery. + +#recovery_target = '' # 'immediate' to end recovery as soon as a + # consistent state is reached + # (change requires restart) +#recovery_target_name = '' # the named restore point to which recovery will proceed + # (change requires restart) +#recovery_target_time = '' # the time stamp up to which recovery will proceed + # (change requires restart) +#recovery_target_xid = '' # the transaction ID up to which recovery will proceed + # (change requires restart) +#recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed + # (change requires restart) +#recovery_target_inclusive = on # Specifies whether to stop: + # just after the specified recovery target (on) + # just before the recovery target (off) + # (change requires restart) +#recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID + # (change requires restart) +#recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown' + # (change requires restart) + + +#------------------------------------------------------------------------------ +# REPLICATION +#------------------------------------------------------------------------------ + +# - Sending Servers - + +# Set these on the primary and on any standby that will send replication data. + +#max_wal_senders = 10 # max number of walsender processes + # (change requires restart) +#max_replication_slots = 10 # max number of replication slots + # (change requires restart) +#wal_keep_size = 0 # in megabytes; 0 disables +#max_slot_wal_keep_size = -1 # in megabytes; -1 disables +#wal_sender_timeout = 60s # in milliseconds; 0 disables +#track_commit_timestamp = off # collect timestamp of transaction commit + # (change requires restart) + +# - Primary Server - + +# These settings are ignored on a standby server. + +#synchronous_standby_names = '' # standby servers that provide sync rep + # method to choose sync standbys, number of sync standbys, + # and comma-separated list of application_name + # from standby(s); '*' = all +#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed + +# - Standby Servers - + +# These settings are ignored on a primary server. + +#primary_conninfo = '' # connection string to sending server +#primary_slot_name = '' # replication slot on sending server +#promote_trigger_file = '' # file name whose presence ends recovery +#hot_standby = on # "off" disallows queries during recovery + # (change requires restart) +#max_standby_archive_delay = 30s # max delay before canceling queries + # when reading WAL from archive; + # -1 allows indefinite delay +#max_standby_streaming_delay = 30s # max delay before canceling queries + # when reading streaming WAL; + # -1 allows indefinite delay +#wal_receiver_create_temp_slot = off # create temp slot if primary_slot_name + # is not set +#wal_receiver_status_interval = 10s # send replies at least this often + # 0 disables +#hot_standby_feedback = off # send info from standby to prevent + # query conflicts +#wal_receiver_timeout = 60s # time that receiver waits for + # communication from primary + # in milliseconds; 0 disables +#wal_retrieve_retry_interval = 5s # time to wait before retrying to + # retrieve WAL after a failed attempt +#recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery + +# - Subscribers - + +# These settings are ignored on a publisher. + +#max_logical_replication_workers = 4 # taken from max_worker_processes + # (change requires restart) +#max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers + + +#------------------------------------------------------------------------------ +# QUERY TUNING +#------------------------------------------------------------------------------ + +# - Planner Method Configuration - + +#enable_async_append = on +#enable_bitmapscan = on +#enable_gathermerge = on +#enable_hashagg = on +#enable_hashjoin = on +#enable_incremental_sort = on +#enable_indexscan = on +#enable_indexonlyscan = on +#enable_material = on +#enable_memoize = on +#enable_mergejoin = on +#enable_nestloop = on +#enable_parallel_append = on +#enable_parallel_hash = on +#enable_partition_pruning = on +#enable_partitionwise_join = off +#enable_partitionwise_aggregate = off +#enable_seqscan = on +#enable_sort = on +#enable_tidscan = on + +# - Planner Cost Constants - + +#seq_page_cost = 1.0 # measured on an arbitrary scale +random_page_cost = 1.1 # same scale as above +#cpu_tuple_cost = 0.01 # same scale as above +#cpu_index_tuple_cost = 0.005 # same scale as above +#cpu_operator_cost = 0.0025 # same scale as above +#parallel_setup_cost = 1000.0 # same scale as above +#parallel_tuple_cost = 0.1 # same scale as above +#min_parallel_table_scan_size = 8MB +#min_parallel_index_scan_size = 512kB +effective_cache_size = 24GB + +#jit_above_cost = 100000 # perform JIT compilation if available + # and query more expensive than this; + # -1 disables +#jit_inline_above_cost = 500000 # inline small functions if query is + # more expensive than this; -1 disables +#jit_optimize_above_cost = 500000 # use expensive JIT optimizations if + # query is more expensive than this; + # -1 disables + +# - Genetic Query Optimizer - + +#geqo = on +#geqo_threshold = 12 +#geqo_effort = 5 # range 1-10 +#geqo_pool_size = 0 # selects default based on effort +#geqo_generations = 0 # selects default based on effort +#geqo_selection_bias = 2.0 # range 1.5-2.0 +#geqo_seed = 0.0 # range 0.0-1.0 + +# - Other Planner Options - + +default_statistics_target = 100 # range 1-10000 +#constraint_exclusion = partition # on, off, or partition +#cursor_tuple_fraction = 0.1 # range 0.0-1.0 +#from_collapse_limit = 8 +#jit = on # allow JIT compilation +#join_collapse_limit = 8 # 1 disables collapsing of explicit + # JOIN clauses +#plan_cache_mode = auto # auto, force_generic_plan or + # force_custom_plan +#recursive_worktable_factor = 10.0 # range 0.001-1000000 + + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - Where to Log - + +#log_destination = 'stderr' # Valid values are combinations of + # stderr, csvlog, jsonlog, syslog, and + # eventlog, depending on platform. + # csvlog and jsonlog require + # logging_collector to be on. + +# This is used when logging to stderr: +#logging_collector = off # Enable capturing of stderr, jsonlog, + # and csvlog into log files. Required + # to be on for csvlogs and jsonlogs. + # (change requires restart) + +# These are only used if logging_collector is on: +#log_directory = 'log' # directory where log files are written, + # can be absolute or relative to PGDATA +#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, + # can include strftime() escapes +#log_file_mode = 0600 # creation mode for log files, + # begin with 0 to use octal notation +#log_rotation_age = 1d # Automatic rotation of logfiles will + # happen after that time. 0 disables. +#log_rotation_size = 10MB # Automatic rotation of logfiles will + # happen after that much log output. + # 0 disables. +#log_truncate_on_rotation = off # If on, an existing log file with the + # same name as the new log file will be + # truncated rather than appended to. + # But such truncation only occurs on + # time-driven rotation, not on restarts + # or size-driven rotation. Default is + # off, meaning append to existing files + # in all cases. + +# These are relevant when logging to syslog: +#syslog_facility = 'LOCAL0' +#syslog_ident = 'postgres' +#syslog_sequence_numbers = on +#syslog_split_messages = on + +# This is only relevant when logging to eventlog (Windows): +# (change requires restart) +#event_source = 'PostgreSQL' + +# - When to Log - + +#log_min_messages = warning # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic + +#log_min_error_statement = error # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic (effectively off) + +#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements + # and their durations, > 0 logs only + # statements running at least this number + # of milliseconds + +#log_min_duration_sample = -1 # -1 is disabled, 0 logs a sample of statements + # and their durations, > 0 logs only a sample of + # statements running at least this number + # of milliseconds; + # sample fraction is determined by log_statement_sample_rate + +#log_statement_sample_rate = 1.0 # fraction of logged statements exceeding + # log_min_duration_sample to be logged; + # 1.0 logs all such statements, 0.0 never logs + + +#log_transaction_sample_rate = 0.0 # fraction of transactions whose statements + # are logged regardless of their duration; 1.0 logs all + # statements from all transactions, 0.0 never logs + +#log_startup_progress_interval = 10s # Time between progress updates for + # long-running startup operations. + # 0 disables the feature, > 0 indicates + # the interval in milliseconds. + +# - What to Log - + +#debug_print_parse = off +#debug_print_rewritten = off +#debug_print_plan = off +#debug_pretty_print = on +#log_autovacuum_min_duration = 10min # log autovacuum activity; + # -1 disables, 0 logs all actions and + # their durations, > 0 logs only + # actions running at least this number + # of milliseconds. +#log_checkpoints = on +#log_connections = off +#log_disconnections = off +#log_duration = off +#log_error_verbosity = default # terse, default, or verbose messages +#log_hostname = off +#log_line_prefix = '%m [%p] ' # special values: + # %a = application name + # %u = user name + # %d = database name + # %r = remote host and port + # %h = remote host + # %b = backend type + # %p = process ID + # %P = process ID of parallel group leader + # %t = timestamp without milliseconds + # %m = timestamp with milliseconds + # %n = timestamp with milliseconds (as a Unix epoch) + # %Q = query ID (0 if none or not computed) + # %i = command tag + # %e = SQL state + # %c = session ID + # %l = session line number + # %s = session start timestamp + # %v = virtual transaction ID + # %x = transaction ID (0 if none) + # %q = stop here in non-session + # processes + # %% = '%' + # e.g. '<%u%%%d> ' +#log_lock_waits = off # log lock waits >= deadlock_timeout +#log_recovery_conflict_waits = off # log standby recovery conflict waits + # >= deadlock_timeout +#log_parameter_max_length = -1 # when logging statements, limit logged + # bind-parameter values to N bytes; + # -1 means print in full, 0 disables +#log_parameter_max_length_on_error = 0 # when logging an error, limit logged + # bind-parameter values to N bytes; + # -1 means print in full, 0 disables +#log_statement = 'none' # none, ddl, mod, all +#log_replication_commands = off +#log_temp_files = -1 # log temporary files equal or larger + # than the specified size in kilobytes; + # -1 disables, 0 logs all temp files +log_timezone = 'Etc/UTC' + + +#------------------------------------------------------------------------------ +# PROCESS TITLE +#------------------------------------------------------------------------------ + +#cluster_name = '' # added to process titles if nonempty + # (change requires restart) +#update_process_title = on + + +#------------------------------------------------------------------------------ +# STATISTICS +#------------------------------------------------------------------------------ + +# - Cumulative Query and Index Statistics - + +#track_activities = on +#track_activity_query_size = 1024 # (change requires restart) +#track_counts = on +#track_io_timing = off +#track_wal_io_timing = off +#track_functions = none # none, pl, all +#stats_fetch_consistency = cache + + +# - Monitoring - + +#compute_query_id = auto +#log_statement_stats = off +#log_parser_stats = off +#log_planner_stats = off +#log_executor_stats = off + + +#------------------------------------------------------------------------------ +# AUTOVACUUM +#------------------------------------------------------------------------------ + +#autovacuum = on # Enable autovacuum subprocess? 'on' + # requires track_counts to also be on. +#autovacuum_max_workers = 3 # max number of autovacuum subprocesses + # (change requires restart) +#autovacuum_naptime = 1min # time between autovacuum runs +#autovacuum_vacuum_threshold = 50 # min number of row updates before + # vacuum +#autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts + # before vacuum; -1 disables insert + # vacuums +#autovacuum_analyze_threshold = 50 # min number of row updates before + # analyze +#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum +#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table + # size before insert vacuum +#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze +#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum + # (change requires restart) +#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age + # before forced vacuum + # (change requires restart) +#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for + # autovacuum, in milliseconds; + # -1 means use vacuum_cost_delay +#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for + # autovacuum, -1 means use + # vacuum_cost_limit + + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Statement Behavior - + +#client_min_messages = notice # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # log + # notice + # warning + # error +#search_path = '"$user", public' # schema names +#row_security = on +#default_table_access_method = 'heap' +#default_tablespace = '' # a tablespace name, '' uses the default +#default_toast_compression = 'pglz' # 'pglz' or 'lz4' +#temp_tablespaces = '' # a list of tablespace names, '' uses + # only default tablespace +#check_function_bodies = on +#default_transaction_isolation = 'read committed' +#default_transaction_read_only = off +#default_transaction_deferrable = off +#session_replication_role = 'origin' +#statement_timeout = 0 # in milliseconds, 0 is disabled +#lock_timeout = 0 # in milliseconds, 0 is disabled +#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled +#idle_session_timeout = 0 # in milliseconds, 0 is disabled +#vacuum_freeze_table_age = 150000000 +#vacuum_freeze_min_age = 50000000 +#vacuum_failsafe_age = 1600000000 +#vacuum_multixact_freeze_table_age = 150000000 +#vacuum_multixact_freeze_min_age = 5000000 +#vacuum_multixact_failsafe_age = 1600000000 +#bytea_output = 'hex' # hex, escape +#xmlbinary = 'base64' +#xmloption = 'content' +#gin_pending_list_limit = 4MB + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +#intervalstyle = 'postgres' +timezone = 'Etc/UTC' +#timezone_abbreviations = 'Default' # Select the set of available time zone + # abbreviations. Currently, there are + # Default + # Australia (historical usage) + # India + # You can create your own file in + # share/timezonesets/. +#extra_float_digits = 1 # min -15, max 3; any value >0 actually + # selects precise output mode +#client_encoding = sql_ascii # actually, defaults to database + # encoding + +# These settings are initialized by initdb, but they can be changed. +lc_messages = 'en_US.utf8' # locale for system error message + # strings +lc_monetary = 'en_US.utf8' # locale for monetary formatting +lc_numeric = 'en_US.utf8' # locale for number formatting +lc_time = 'en_US.utf8' # locale for time formatting + +# default configuration for text search +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +#local_preload_libraries = '' +#session_preload_libraries = '' +#shared_preload_libraries = '' # (change requires restart) +#jit_provider = 'llvmjit' # JIT library to use + +# - Other Defaults - + +#dynamic_library_path = '$libdir' +#extension_destdir = '' # prepend path when loading extensions + # and shared objects (added by Debian) +#gin_fuzzy_search_limit = 0 + + +#------------------------------------------------------------------------------ +# LOCK MANAGEMENT +#------------------------------------------------------------------------------ + +#deadlock_timeout = 1s +#max_locks_per_transaction = 64 # min 10 + # (change requires restart) +#max_pred_locks_per_transaction = 64 # min 10 + # (change requires restart) +#max_pred_locks_per_relation = -2 # negative values mean + # (max_pred_locks_per_transaction + # / -max_pred_locks_per_relation) - 1 +#max_pred_locks_per_page = 2 # min 0 + + +#------------------------------------------------------------------------------ +# VERSION AND PLATFORM COMPATIBILITY +#------------------------------------------------------------------------------ + +# - Previous PostgreSQL Versions - + +#array_nulls = on +#backslash_quote = safe_encoding # on, off, or safe_encoding +#escape_string_warning = on +#lo_compat_privileges = off +#quote_all_identifiers = off +#standard_conforming_strings = on +#synchronize_seqscans = on + +# - Other Platforms and Clients - + +#transform_null_equals = off + + +#------------------------------------------------------------------------------ +# ERROR HANDLING +#------------------------------------------------------------------------------ + +#exit_on_error = off # terminate session on any error? +#restart_after_crash = on # reinitialize after backend crash? +#data_sync_retry = off # retry or panic on failure to fsync + # data? + # (change requires restart) +#recovery_init_sync_method = fsync # fsync, syncfs (Linux 5.8+) + + +#------------------------------------------------------------------------------ +# CONFIG FILE INCLUDES +#------------------------------------------------------------------------------ + +# These options allow settings to be loaded from files other than the +# default postgresql.conf. Note that these are directives, not variable +# assignments, so they can usefully be given more than once. + +#include_dir = '...' # include files ending in '.conf' from + # a directory, e.g., 'conf.d' +#include_if_exists = '...' # include file only if it exists +#include = '...' # include file + + +#------------------------------------------------------------------------------ +# CUSTOMIZED OPTIONS +#------------------------------------------------------------------------------ + +# Add settings for extensions here diff --git a/config/environments/mainnet/public.node.config.toml b/config/environments/mainnet/public.node.config.toml new file mode 100644 index 0000000000..28bc77685c --- /dev/null +++ b/config/environments/mainnet/public.node.config.toml @@ -0,0 +1,65 @@ +[Log] +Environment = "development" # "production" or "development" +Level = "info" +Outputs = ["stderr"] + +[StateDB] +User = "state_user" +Password = "state_password" +Name = "state_db" +Host = "zkevm-state-db" +Port = "5432" +EnableLog = false +MaxConns = 200 + +[Pool] +MaxTxBytesSize=100132 +MaxTxDataBytesSize=100000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "zkevm-pool-db" + Port = "5432" + EnableLog = false + MaxConns = 200 + +[Etherman] +URL = "http://your.L1node.url" +MultiGasProvider = false + [Etherman.Etherscan] + ApiKey = "" + +[RPC] +Host = "0.0.0.0" +Port = 8545 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 5000 +SequencerNodeURI = "https://zkevm-rpc.com" +EnableL2SuggestedGasPricePolling = false + [RPC.WebSockets] + Enabled = true + Port = 8546 + +[Synchronizer] +SyncInterval = "2s" +SyncChunkSize = 100 +TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc + +[MTClient] +URI = "zkevm-prover:50061" + +[Executor] +URI = "zkevm-prover:50071" + +[Metrics] +Host = "0.0.0.0" +Port = 9091 +Enabled = false +ProfilingHost = "0.0.0.0" +ProfilingPort = 6060 +ProfilingEnabled = false diff --git a/config/environments/mainnet/public.prover.config.json b/config/environments/mainnet/public.prover.config.json new file mode 100644 index 0000000000..8d0c93b81b --- /dev/null +++ b/config/environments/mainnet/public.prover.config.json @@ -0,0 +1,113 @@ +{ + "runProverServer": false, + "runProverServerMock": false, + "runProverClient": false, + + "runExecutorServer": true, + "runExecutorClient": false, + "runExecutorClientMultithread": false, + + "runStateDBServer": true, + "runStateDBTest": false, + + "runAggregatorServer": false, + "runAggregatorClient": false, + + "runFileGenProof": false, + "runFileGenBatchProof": false, + "runFileGenAggregatedProof": false, + "runFileGenFinalProof": false, + "runFileProcessBatch": false, + "runFileProcessBatchMultithread": false, + + "runKeccakScriptGenerator": false, + "runKeccakTest": false, + "runStorageSMTest": false, + "runBinarySMTest": false, + "runMemAlignSMTest": false, + "runSHA256Test": false, + "runBlakeTest": false, + + "executeInParallel": true, + "useMainExecGenerated": false, + "saveRequestToFile": false, + "saveInputToFile": false, + "saveDbReadsToFile": false, + "saveDbReadsToFileOnChange": false, + "saveOutputToFile": false, + "saveResponseToFile": false, + "loadDBToMemCache": true, + "opcodeTracer": false, + "logRemoteDbReads": false, + "logExecutorServerResponses": false, + + "proverServerPort": 50051, + "proverServerMockPort": 50052, + "proverServerMockTimeout": 10000000, + "proverClientPort": 50051, + "proverClientHost": "127.0.0.1", + + "executorServerPort": 50071, + "executorROMLineTraces": false, + "executorClientPort": 50071, + "executorClientHost": "127.0.0.1", + + "stateDBServerPort": 50061, + "stateDBURL": "local", + + "aggregatorServerPort": 50081, + "aggregatorClientPort": 50081, + "aggregatorClientHost": "127.0.0.1", + + "inputFile": "input_executor.json", + "outputPath": "output", + "cmPolsFile_disabled": "zkevm.commit", + "cmPolsFileC12a_disabled": "zkevm.c12a.commit", + "cmPolsFileRecursive1_disabled": "zkevm.recursive1.commit", + "constPolsFile": "zkevm.const", + "constPolsC12aFile": "zkevm.c12a.const", + "constPolsRecursive1File": "zkevm.recursive1.const", + "mapConstPolsFile": false, + "constantsTreeFile": "zkevm.consttree", + "constantsTreeC12aFile": "zkevm.c12a.consttree", + "constantsTreeRecursive1File": "zkevm.recursive1.consttree", + "mapConstantsTreeFile": false, + "starkFile": "zkevm.prove.json", + "starkZkIn": "zkevm.proof.zkin.json", + "starkZkInC12a":"zkevm.c12a.zkin.proof.json", + "starkFileRecursive1": "zkevm.recursive1.proof.json", + "verifierFile": "zkevm.verifier.dat", + "verifierFileRecursive1": "zkevm.recursive1.verifier.dat", + "witnessFile_disabled": "zkevm.witness.wtns", + "witnessFileRecursive1": "zkevm.recursive1.witness.wtns", + "execC12aFile": "zkevm.c12a.exec", + "execRecursive1File": "zkevm.recursive1.exec", + "starkVerifierFile": "zkevm.g16.0001.zkey", + "publicStarkFile": "zkevm.public.json", + "publicFile": "public.json", + "proofFile": "proof.json", + "keccakScriptFile": "keccak_script.json", + "keccakPolsFile_DISABLED": "keccak_pols.json", + "keccakConnectionsFile": "keccak_connections.json", + "starkInfoFile": "zkevm.starkinfo.json", + "starkInfoC12aFile": "zkevm.c12a.starkinfo.json", + "starkInfoRecursive1File": "zkevm.recursive1.starkinfo.json", + "databaseURL": "postgresql://prover_user:prover_pass@zkevm-state-db:5432/prover_db", + "dbNodesTableName": "state.nodes", + "dbProgramTableName": "state.program", + "dbAsyncWrite": false, + "dbMultiWrite": true, + "dbConnectionsPool": true, + "dbNumberOfPoolConnections": 30, + "dbMetrics": true, + "dbClearCache": false, + "dbGetTree": true, + "dbReadOnly": false, + "dbMTCacheSize": 8192, + "dbProgramCacheSize": 1024, + "cleanerPollingPeriod": 600, + "requestsPersistence": 3600, + "maxExecutorThreads": 20, + "maxProverThreads": 8, + "maxStateDBThreads": 8 +} \ No newline at end of file diff --git a/config/environments/public/example.env b/config/environments/public/example.env new file mode 100644 index 0000000000..bf0db2e035 --- /dev/null +++ b/config/environments/public/example.env @@ -0,0 +1,9 @@ +ZKEVM_NETWORK = "testnet" +# URL of a JSON RPC for Goerli +ZKEVM_NODE_ETHERMAN_URL = "http://your.L1node.url" +# PATH WHERE THE STATEDB POSTGRES CONTAINER WILL STORE PERSISTENT DATA +ZKEVM_NODE_STATEDB_DATA_DIR = "/path/to/persistent/data/statedb" +# PATH WHERE THE POOLDB POSTGRES CONTAINER WILL STORE PERSISTENT DATA +ZKEVM_NODE_POOLDB_DATA_DIR = "/path/to/persistent/data/pooldb" +# OPTIONAL, UNCOMENT IF YOU WANT TO DO ADVANCED CONFIG +# ZKEVM_ADVANCED_CONFIG_DIR = "/should/be/same/path/as/ZKEVM_CONFIG_DIR" \ No newline at end of file diff --git a/config/environments/public/postgresql.conf b/config/environments/public/postgresql.conf new file mode 100644 index 0000000000..51dff68697 --- /dev/null +++ b/config/environments/public/postgresql.conf @@ -0,0 +1,815 @@ +# ----------------------------- +# PostgreSQL configuration file +# ----------------------------- +# +# This file consists of lines of the form: +# +# name = value +# +# (The "=" is optional.) Whitespace may be used. Comments are introduced with +# "#" anywhere on a line. The complete list of parameter names and allowed +# values can be found in the PostgreSQL documentation. +# +# The commented-out settings shown in this file represent the default values. +# Re-commenting a setting is NOT sufficient to revert it to the default value; +# you need to reload the server. +# +# This file is read on server startup and when the server receives a SIGHUP +# signal. If you edit the file on a running system, you have to SIGHUP the +# server for the changes to take effect, run "pg_ctl reload", or execute +# "SELECT pg_reload_conf()". Some parameters, which are marked below, +# require a server shutdown and restart to take effect. +# +# Any parameter can also be given as a command-line option to the server, e.g., +# "postgres -c log_connections=on". Some parameters can be changed at run time +# with the "SET" SQL command. +# +# Memory units: B = bytes Time units: us = microseconds +# kB = kilobytes ms = milliseconds +# MB = megabytes s = seconds +# GB = gigabytes min = minutes +# TB = terabytes h = hours +# d = days + + +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +# The default values of these variables are driven from the -D command-line +# option or PGDATA environment variable, represented here as ConfigDir. + +#data_directory = 'ConfigDir' # use data in another directory + # (change requires restart) +#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file + # (change requires restart) +#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file + # (change requires restart) + +# If external_pid_file is not explicitly set, no extra PID file is written. +#external_pid_file = '' # write an extra PID file + # (change requires restart) + + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' + # comma-separated list of addresses; + # defaults to 'localhost'; use '*' for all + # (change requires restart) +#port = 5432 # (change requires restart) +max_connections = 100 # (change requires restart) +#superuser_reserved_connections = 3 # (change requires restart) +#unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories + # (change requires restart) +#unix_socket_group = '' # (change requires restart) +#unix_socket_permissions = 0777 # begin with 0 to use octal notation + # (change requires restart) +#bonjour = off # advertise server via Bonjour + # (change requires restart) +#bonjour_name = '' # defaults to the computer name + # (change requires restart) + +# - TCP settings - +# see "man tcp" for details + +#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; + # 0 selects the system default +#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; + # 0 selects the system default +#tcp_keepalives_count = 0 # TCP_KEEPCNT; + # 0 selects the system default +#tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds; + # 0 selects the system default + +#client_connection_check_interval = 0 # time between checks for client + # disconnection while running queries; + # 0 for never + +# - Authentication - + +#authentication_timeout = 1min # 1s-600s +#password_encryption = scram-sha-256 # scram-sha-256 or md5 +#db_user_namespace = off + +# GSSAPI using Kerberos +#krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab' +#krb_caseins_users = off + +# - SSL - + +#ssl = off +#ssl_ca_file = '' +#ssl_cert_file = 'server.crt' +#ssl_crl_file = '' +#ssl_crl_dir = '' +#ssl_key_file = 'server.key' +#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers +#ssl_prefer_server_ciphers = on +#ssl_ecdh_curve = 'prime256v1' +#ssl_min_protocol_version = 'TLSv1.2' +#ssl_max_protocol_version = '' +#ssl_dh_params_file = '' +#ssl_passphrase_command = '' +#ssl_passphrase_command_supports_reload = off + + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +shared_buffers = 8GB # min 128kB + # (change requires restart) +#huge_pages = try # on, off, or try + # (change requires restart) +#huge_page_size = 0 # zero for system default + # (change requires restart) +temp_buffers = 64MB # min 800kB +#max_prepared_transactions = 0 # zero disables the feature + # (change requires restart) +# Caution: it is not advisable to set max_prepared_transactions nonzero unless +# you actively intend to use prepared transactions. +work_mem = 104857kB # min 64kB +#hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem +maintenance_work_mem = 2GB # min 1MB +#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem +#logical_decoding_work_mem = 64MB # min 64kB +#max_stack_depth = 2MB # min 100kB +#shared_memory_type = mmap # the default is the first option + # supported by the operating system: + # mmap + # sysv + # windows + # (change requires restart) +dynamic_shared_memory_type = posix # the default is usually the first option + # supported by the operating system: + # posix + # sysv + # windows + # mmap + # (change requires restart) +#min_dynamic_shared_memory = 0MB # (change requires restart) + +# - Disk - + +#temp_file_limit = -1 # limits per-process temp file space + # in kilobytes, or -1 for no limit + +# - Kernel Resources - + +#max_files_per_process = 1000 # min 64 + # (change requires restart) + +# - Cost-Based Vacuum Delay - + +#vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) +#vacuum_cost_page_hit = 1 # 0-10000 credits +#vacuum_cost_page_miss = 2 # 0-10000 credits +#vacuum_cost_page_dirty = 20 # 0-10000 credits +#vacuum_cost_limit = 200 # 1-10000 credits + +# - Background Writer - + +#bgwriter_delay = 200ms # 10-10000ms between rounds +#bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables +#bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round +#bgwriter_flush_after = 512kB # measured in pages, 0 disables + +# - Asynchronous Behavior - + +#backend_flush_after = 0 # measured in pages, 0 disables +effective_io_concurrency = 300 # 1-1000; 0 disables prefetching +#maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching +max_worker_processes = 16 # (change requires restart) +max_parallel_workers_per_gather = 4 # taken from max_parallel_workers +max_parallel_maintenance_workers = 4 # taken from max_parallel_workers +max_parallel_workers = 16 # maximum number of max_worker_processes that + # can be used in parallel operations +#parallel_leader_participation = on +#old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate + # (change requires restart) + + +#------------------------------------------------------------------------------ +# WRITE-AHEAD LOG +#------------------------------------------------------------------------------ + +# - Settings - + +#wal_level = replica # minimal, replica, or logical + # (change requires restart) +#fsync = on # flush data to disk for crash safety + # (turning this off can cause + # unrecoverable data corruption) +#synchronous_commit = on # synchronization level; + # off, local, remote_write, remote_apply, or on +#wal_sync_method = fsync # the default is the first option + # supported by the operating system: + # open_datasync + # fdatasync (default on Linux and FreeBSD) + # fsync + # fsync_writethrough + # open_sync +#full_page_writes = on # recover from partial page writes +#wal_log_hints = off # also do full page writes of non-critical updates + # (change requires restart) +#wal_compression = off # enables compression of full-page writes; + # off, pglz, lz4, zstd, or on +#wal_init_zero = on # zero-fill new WAL files +#wal_recycle = on # recycle WAL files +wal_buffers = 16MB # min 32kB, -1 sets based on shared_buffers + # (change requires restart) +#wal_writer_delay = 200ms # 1-10000 milliseconds +#wal_writer_flush_after = 1MB # measured in pages, 0 disables +#wal_skip_threshold = 2MB + +#commit_delay = 0 # range 0-100000, in microseconds +#commit_siblings = 5 # range 1-1000 + +# - Checkpoints - + +#checkpoint_timeout = 5min # range 30s-1d +checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0 +#checkpoint_flush_after = 256kB # measured in pages, 0 disables +#checkpoint_warning = 30s # 0 disables +max_wal_size = 8GB +min_wal_size = 2GB + +# - Prefetching during recovery - + +#recovery_prefetch = try # prefetch pages referenced in the WAL? +#wal_decode_buffer_size = 512kB # lookahead window used for prefetching + # (change requires restart) + +# - Archiving - + +#archive_mode = off # enables archiving; off, on, or always + # (change requires restart) +#archive_library = '' # library to use to archive a logfile segment + # (empty string indicates archive_command should + # be used) +#archive_command = '' # command to use to archive a logfile segment + # placeholders: %p = path of file to archive + # %f = file name only + # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' +#archive_timeout = 0 # force a logfile segment switch after this + # number of seconds; 0 disables + +# - Archive Recovery - + +# These are only used in recovery mode. + +#restore_command = '' # command to use to restore an archived logfile segment + # placeholders: %p = path of file to restore + # %f = file name only + # e.g. 'cp /mnt/server/archivedir/%f %p' +#archive_cleanup_command = '' # command to execute at every restartpoint +#recovery_end_command = '' # command to execute at completion of recovery + +# - Recovery Target - + +# Set these only when performing a targeted recovery. + +#recovery_target = '' # 'immediate' to end recovery as soon as a + # consistent state is reached + # (change requires restart) +#recovery_target_name = '' # the named restore point to which recovery will proceed + # (change requires restart) +#recovery_target_time = '' # the time stamp up to which recovery will proceed + # (change requires restart) +#recovery_target_xid = '' # the transaction ID up to which recovery will proceed + # (change requires restart) +#recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed + # (change requires restart) +#recovery_target_inclusive = on # Specifies whether to stop: + # just after the specified recovery target (on) + # just before the recovery target (off) + # (change requires restart) +#recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID + # (change requires restart) +#recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown' + # (change requires restart) + + +#------------------------------------------------------------------------------ +# REPLICATION +#------------------------------------------------------------------------------ + +# - Sending Servers - + +# Set these on the primary and on any standby that will send replication data. + +#max_wal_senders = 10 # max number of walsender processes + # (change requires restart) +#max_replication_slots = 10 # max number of replication slots + # (change requires restart) +#wal_keep_size = 0 # in megabytes; 0 disables +#max_slot_wal_keep_size = -1 # in megabytes; -1 disables +#wal_sender_timeout = 60s # in milliseconds; 0 disables +#track_commit_timestamp = off # collect timestamp of transaction commit + # (change requires restart) + +# - Primary Server - + +# These settings are ignored on a standby server. + +#synchronous_standby_names = '' # standby servers that provide sync rep + # method to choose sync standbys, number of sync standbys, + # and comma-separated list of application_name + # from standby(s); '*' = all +#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed + +# - Standby Servers - + +# These settings are ignored on a primary server. + +#primary_conninfo = '' # connection string to sending server +#primary_slot_name = '' # replication slot on sending server +#promote_trigger_file = '' # file name whose presence ends recovery +#hot_standby = on # "off" disallows queries during recovery + # (change requires restart) +#max_standby_archive_delay = 30s # max delay before canceling queries + # when reading WAL from archive; + # -1 allows indefinite delay +#max_standby_streaming_delay = 30s # max delay before canceling queries + # when reading streaming WAL; + # -1 allows indefinite delay +#wal_receiver_create_temp_slot = off # create temp slot if primary_slot_name + # is not set +#wal_receiver_status_interval = 10s # send replies at least this often + # 0 disables +#hot_standby_feedback = off # send info from standby to prevent + # query conflicts +#wal_receiver_timeout = 60s # time that receiver waits for + # communication from primary + # in milliseconds; 0 disables +#wal_retrieve_retry_interval = 5s # time to wait before retrying to + # retrieve WAL after a failed attempt +#recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery + +# - Subscribers - + +# These settings are ignored on a publisher. + +#max_logical_replication_workers = 4 # taken from max_worker_processes + # (change requires restart) +#max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers + + +#------------------------------------------------------------------------------ +# QUERY TUNING +#------------------------------------------------------------------------------ + +# - Planner Method Configuration - + +#enable_async_append = on +#enable_bitmapscan = on +#enable_gathermerge = on +#enable_hashagg = on +#enable_hashjoin = on +#enable_incremental_sort = on +#enable_indexscan = on +#enable_indexonlyscan = on +#enable_material = on +#enable_memoize = on +#enable_mergejoin = on +#enable_nestloop = on +#enable_parallel_append = on +#enable_parallel_hash = on +#enable_partition_pruning = on +#enable_partitionwise_join = off +#enable_partitionwise_aggregate = off +#enable_seqscan = on +#enable_sort = on +#enable_tidscan = on + +# - Planner Cost Constants - + +#seq_page_cost = 1.0 # measured on an arbitrary scale +random_page_cost = 1.1 # same scale as above +#cpu_tuple_cost = 0.01 # same scale as above +#cpu_index_tuple_cost = 0.005 # same scale as above +#cpu_operator_cost = 0.0025 # same scale as above +#parallel_setup_cost = 1000.0 # same scale as above +#parallel_tuple_cost = 0.1 # same scale as above +#min_parallel_table_scan_size = 8MB +#min_parallel_index_scan_size = 512kB +effective_cache_size = 24GB + +#jit_above_cost = 100000 # perform JIT compilation if available + # and query more expensive than this; + # -1 disables +#jit_inline_above_cost = 500000 # inline small functions if query is + # more expensive than this; -1 disables +#jit_optimize_above_cost = 500000 # use expensive JIT optimizations if + # query is more expensive than this; + # -1 disables + +# - Genetic Query Optimizer - + +#geqo = on +#geqo_threshold = 12 +#geqo_effort = 5 # range 1-10 +#geqo_pool_size = 0 # selects default based on effort +#geqo_generations = 0 # selects default based on effort +#geqo_selection_bias = 2.0 # range 1.5-2.0 +#geqo_seed = 0.0 # range 0.0-1.0 + +# - Other Planner Options - + +default_statistics_target = 100 # range 1-10000 +#constraint_exclusion = partition # on, off, or partition +#cursor_tuple_fraction = 0.1 # range 0.0-1.0 +#from_collapse_limit = 8 +#jit = on # allow JIT compilation +#join_collapse_limit = 8 # 1 disables collapsing of explicit + # JOIN clauses +#plan_cache_mode = auto # auto, force_generic_plan or + # force_custom_plan +#recursive_worktable_factor = 10.0 # range 0.001-1000000 + + +#------------------------------------------------------------------------------ +# REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - Where to Log - + +#log_destination = 'stderr' # Valid values are combinations of + # stderr, csvlog, jsonlog, syslog, and + # eventlog, depending on platform. + # csvlog and jsonlog require + # logging_collector to be on. + +# This is used when logging to stderr: +#logging_collector = off # Enable capturing of stderr, jsonlog, + # and csvlog into log files. Required + # to be on for csvlogs and jsonlogs. + # (change requires restart) + +# These are only used if logging_collector is on: +#log_directory = 'log' # directory where log files are written, + # can be absolute or relative to PGDATA +#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, + # can include strftime() escapes +#log_file_mode = 0600 # creation mode for log files, + # begin with 0 to use octal notation +#log_rotation_age = 1d # Automatic rotation of logfiles will + # happen after that time. 0 disables. +#log_rotation_size = 10MB # Automatic rotation of logfiles will + # happen after that much log output. + # 0 disables. +#log_truncate_on_rotation = off # If on, an existing log file with the + # same name as the new log file will be + # truncated rather than appended to. + # But such truncation only occurs on + # time-driven rotation, not on restarts + # or size-driven rotation. Default is + # off, meaning append to existing files + # in all cases. + +# These are relevant when logging to syslog: +#syslog_facility = 'LOCAL0' +#syslog_ident = 'postgres' +#syslog_sequence_numbers = on +#syslog_split_messages = on + +# This is only relevant when logging to eventlog (Windows): +# (change requires restart) +#event_source = 'PostgreSQL' + +# - When to Log - + +#log_min_messages = warning # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic + +#log_min_error_statement = error # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic (effectively off) + +#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements + # and their durations, > 0 logs only + # statements running at least this number + # of milliseconds + +#log_min_duration_sample = -1 # -1 is disabled, 0 logs a sample of statements + # and their durations, > 0 logs only a sample of + # statements running at least this number + # of milliseconds; + # sample fraction is determined by log_statement_sample_rate + +#log_statement_sample_rate = 1.0 # fraction of logged statements exceeding + # log_min_duration_sample to be logged; + # 1.0 logs all such statements, 0.0 never logs + + +#log_transaction_sample_rate = 0.0 # fraction of transactions whose statements + # are logged regardless of their duration; 1.0 logs all + # statements from all transactions, 0.0 never logs + +#log_startup_progress_interval = 10s # Time between progress updates for + # long-running startup operations. + # 0 disables the feature, > 0 indicates + # the interval in milliseconds. + +# - What to Log - + +#debug_print_parse = off +#debug_print_rewritten = off +#debug_print_plan = off +#debug_pretty_print = on +#log_autovacuum_min_duration = 10min # log autovacuum activity; + # -1 disables, 0 logs all actions and + # their durations, > 0 logs only + # actions running at least this number + # of milliseconds. +#log_checkpoints = on +#log_connections = off +#log_disconnections = off +#log_duration = off +#log_error_verbosity = default # terse, default, or verbose messages +#log_hostname = off +#log_line_prefix = '%m [%p] ' # special values: + # %a = application name + # %u = user name + # %d = database name + # %r = remote host and port + # %h = remote host + # %b = backend type + # %p = process ID + # %P = process ID of parallel group leader + # %t = timestamp without milliseconds + # %m = timestamp with milliseconds + # %n = timestamp with milliseconds (as a Unix epoch) + # %Q = query ID (0 if none or not computed) + # %i = command tag + # %e = SQL state + # %c = session ID + # %l = session line number + # %s = session start timestamp + # %v = virtual transaction ID + # %x = transaction ID (0 if none) + # %q = stop here in non-session + # processes + # %% = '%' + # e.g. '<%u%%%d> ' +#log_lock_waits = off # log lock waits >= deadlock_timeout +#log_recovery_conflict_waits = off # log standby recovery conflict waits + # >= deadlock_timeout +#log_parameter_max_length = -1 # when logging statements, limit logged + # bind-parameter values to N bytes; + # -1 means print in full, 0 disables +#log_parameter_max_length_on_error = 0 # when logging an error, limit logged + # bind-parameter values to N bytes; + # -1 means print in full, 0 disables +#log_statement = 'none' # none, ddl, mod, all +#log_replication_commands = off +#log_temp_files = -1 # log temporary files equal or larger + # than the specified size in kilobytes; + # -1 disables, 0 logs all temp files +log_timezone = 'Etc/UTC' + + +#------------------------------------------------------------------------------ +# PROCESS TITLE +#------------------------------------------------------------------------------ + +#cluster_name = '' # added to process titles if nonempty + # (change requires restart) +#update_process_title = on + + +#------------------------------------------------------------------------------ +# STATISTICS +#------------------------------------------------------------------------------ + +# - Cumulative Query and Index Statistics - + +#track_activities = on +#track_activity_query_size = 1024 # (change requires restart) +#track_counts = on +#track_io_timing = off +#track_wal_io_timing = off +#track_functions = none # none, pl, all +#stats_fetch_consistency = cache + + +# - Monitoring - + +#compute_query_id = auto +#log_statement_stats = off +#log_parser_stats = off +#log_planner_stats = off +#log_executor_stats = off + + +#------------------------------------------------------------------------------ +# AUTOVACUUM +#------------------------------------------------------------------------------ + +#autovacuum = on # Enable autovacuum subprocess? 'on' + # requires track_counts to also be on. +#autovacuum_max_workers = 3 # max number of autovacuum subprocesses + # (change requires restart) +#autovacuum_naptime = 1min # time between autovacuum runs +#autovacuum_vacuum_threshold = 50 # min number of row updates before + # vacuum +#autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts + # before vacuum; -1 disables insert + # vacuums +#autovacuum_analyze_threshold = 50 # min number of row updates before + # analyze +#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum +#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table + # size before insert vacuum +#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze +#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum + # (change requires restart) +#autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age + # before forced vacuum + # (change requires restart) +#autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for + # autovacuum, in milliseconds; + # -1 means use vacuum_cost_delay +#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for + # autovacuum, -1 means use + # vacuum_cost_limit + + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Statement Behavior - + +#client_min_messages = notice # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # log + # notice + # warning + # error +#search_path = '"$user", public' # schema names +#row_security = on +#default_table_access_method = 'heap' +#default_tablespace = '' # a tablespace name, '' uses the default +#default_toast_compression = 'pglz' # 'pglz' or 'lz4' +#temp_tablespaces = '' # a list of tablespace names, '' uses + # only default tablespace +#check_function_bodies = on +#default_transaction_isolation = 'read committed' +#default_transaction_read_only = off +#default_transaction_deferrable = off +#session_replication_role = 'origin' +#statement_timeout = 0 # in milliseconds, 0 is disabled +#lock_timeout = 0 # in milliseconds, 0 is disabled +#idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled +#idle_session_timeout = 0 # in milliseconds, 0 is disabled +#vacuum_freeze_table_age = 150000000 +#vacuum_freeze_min_age = 50000000 +#vacuum_failsafe_age = 1600000000 +#vacuum_multixact_freeze_table_age = 150000000 +#vacuum_multixact_freeze_min_age = 5000000 +#vacuum_multixact_failsafe_age = 1600000000 +#bytea_output = 'hex' # hex, escape +#xmlbinary = 'base64' +#xmloption = 'content' +#gin_pending_list_limit = 4MB + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +#intervalstyle = 'postgres' +timezone = 'Etc/UTC' +#timezone_abbreviations = 'Default' # Select the set of available time zone + # abbreviations. Currently, there are + # Default + # Australia (historical usage) + # India + # You can create your own file in + # share/timezonesets/. +#extra_float_digits = 1 # min -15, max 3; any value >0 actually + # selects precise output mode +#client_encoding = sql_ascii # actually, defaults to database + # encoding + +# These settings are initialized by initdb, but they can be changed. +lc_messages = 'en_US.utf8' # locale for system error message + # strings +lc_monetary = 'en_US.utf8' # locale for monetary formatting +lc_numeric = 'en_US.utf8' # locale for number formatting +lc_time = 'en_US.utf8' # locale for time formatting + +# default configuration for text search +default_text_search_config = 'pg_catalog.english' + +# - Shared Library Preloading - + +#local_preload_libraries = '' +#session_preload_libraries = '' +#shared_preload_libraries = '' # (change requires restart) +#jit_provider = 'llvmjit' # JIT library to use + +# - Other Defaults - + +#dynamic_library_path = '$libdir' +#extension_destdir = '' # prepend path when loading extensions + # and shared objects (added by Debian) +#gin_fuzzy_search_limit = 0 + + +#------------------------------------------------------------------------------ +# LOCK MANAGEMENT +#------------------------------------------------------------------------------ + +#deadlock_timeout = 1s +#max_locks_per_transaction = 64 # min 10 + # (change requires restart) +#max_pred_locks_per_transaction = 64 # min 10 + # (change requires restart) +#max_pred_locks_per_relation = -2 # negative values mean + # (max_pred_locks_per_transaction + # / -max_pred_locks_per_relation) - 1 +#max_pred_locks_per_page = 2 # min 0 + + +#------------------------------------------------------------------------------ +# VERSION AND PLATFORM COMPATIBILITY +#------------------------------------------------------------------------------ + +# - Previous PostgreSQL Versions - + +#array_nulls = on +#backslash_quote = safe_encoding # on, off, or safe_encoding +#escape_string_warning = on +#lo_compat_privileges = off +#quote_all_identifiers = off +#standard_conforming_strings = on +#synchronize_seqscans = on + +# - Other Platforms and Clients - + +#transform_null_equals = off + + +#------------------------------------------------------------------------------ +# ERROR HANDLING +#------------------------------------------------------------------------------ + +#exit_on_error = off # terminate session on any error? +#restart_after_crash = on # reinitialize after backend crash? +#data_sync_retry = off # retry or panic on failure to fsync + # data? + # (change requires restart) +#recovery_init_sync_method = fsync # fsync, syncfs (Linux 5.8+) + + +#------------------------------------------------------------------------------ +# CONFIG FILE INCLUDES +#------------------------------------------------------------------------------ + +# These options allow settings to be loaded from files other than the +# default postgresql.conf. Note that these are directives, not variable +# assignments, so they can usefully be given more than once. + +#include_dir = '...' # include files ending in '.conf' from + # a directory, e.g., 'conf.d' +#include_if_exists = '...' # include file only if it exists +#include = '...' # include file + + +#------------------------------------------------------------------------------ +# CUSTOMIZED OPTIONS +#------------------------------------------------------------------------------ + +# Add settings for extensions here diff --git a/config/environments/public/public.node.config.toml b/config/environments/public/public.node.config.toml new file mode 100644 index 0000000000..b0b9b9e607 --- /dev/null +++ b/config/environments/public/public.node.config.toml @@ -0,0 +1,65 @@ +[Log] +Environment = "development" # "production" or "development" +Level = "info" +Outputs = ["stderr"] + +[StateDB] +User = "state_user" +Password = "state_password" +Name = "state_db" +Host = "zkevm-state-db" +Port = "5432" +EnableLog = false +MaxConns = 200 + +[Pool] +IntervalToRefreshBlockedAddresses = "5m" +MaxTxBytesSize=100132 +MaxTxDataBytesSize=100000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "zkevm-pool-db" + Port = "5432" + EnableLog = false + MaxConns = 200 + +[Etherman] +URL = "http://your.L1node.url" +MultiGasProvider = false + [Etherman.Etherscan] + ApiKey = "" + +[RPC] +Host = "0.0.0.0" +Port = 8545 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 5000 +SequencerNodeURI = "https://rpc.public.zkevm-test.net/" +EnableL2SuggestedGasPricePolling = false + [RPC.WebSockets] + Enabled = true + Port = 8546 + +[Synchronizer] +SyncInterval = "2s" +SyncChunkSize = 100 + +[MTClient] +URI = "zkevm-prover:50061" + +[Executor] +URI = "zkevm-prover:50071" + +[Metrics] +Host = "0.0.0.0" +Port = 9091 +Enabled = false +ProfilingHost = "0.0.0.0" +ProfilingPort = 6060 +ProfilingEnabled = false diff --git a/config/environments/public/public.prover.config.json b/config/environments/public/public.prover.config.json new file mode 100644 index 0000000000..8d0c93b81b --- /dev/null +++ b/config/environments/public/public.prover.config.json @@ -0,0 +1,113 @@ +{ + "runProverServer": false, + "runProverServerMock": false, + "runProverClient": false, + + "runExecutorServer": true, + "runExecutorClient": false, + "runExecutorClientMultithread": false, + + "runStateDBServer": true, + "runStateDBTest": false, + + "runAggregatorServer": false, + "runAggregatorClient": false, + + "runFileGenProof": false, + "runFileGenBatchProof": false, + "runFileGenAggregatedProof": false, + "runFileGenFinalProof": false, + "runFileProcessBatch": false, + "runFileProcessBatchMultithread": false, + + "runKeccakScriptGenerator": false, + "runKeccakTest": false, + "runStorageSMTest": false, + "runBinarySMTest": false, + "runMemAlignSMTest": false, + "runSHA256Test": false, + "runBlakeTest": false, + + "executeInParallel": true, + "useMainExecGenerated": false, + "saveRequestToFile": false, + "saveInputToFile": false, + "saveDbReadsToFile": false, + "saveDbReadsToFileOnChange": false, + "saveOutputToFile": false, + "saveResponseToFile": false, + "loadDBToMemCache": true, + "opcodeTracer": false, + "logRemoteDbReads": false, + "logExecutorServerResponses": false, + + "proverServerPort": 50051, + "proverServerMockPort": 50052, + "proverServerMockTimeout": 10000000, + "proverClientPort": 50051, + "proverClientHost": "127.0.0.1", + + "executorServerPort": 50071, + "executorROMLineTraces": false, + "executorClientPort": 50071, + "executorClientHost": "127.0.0.1", + + "stateDBServerPort": 50061, + "stateDBURL": "local", + + "aggregatorServerPort": 50081, + "aggregatorClientPort": 50081, + "aggregatorClientHost": "127.0.0.1", + + "inputFile": "input_executor.json", + "outputPath": "output", + "cmPolsFile_disabled": "zkevm.commit", + "cmPolsFileC12a_disabled": "zkevm.c12a.commit", + "cmPolsFileRecursive1_disabled": "zkevm.recursive1.commit", + "constPolsFile": "zkevm.const", + "constPolsC12aFile": "zkevm.c12a.const", + "constPolsRecursive1File": "zkevm.recursive1.const", + "mapConstPolsFile": false, + "constantsTreeFile": "zkevm.consttree", + "constantsTreeC12aFile": "zkevm.c12a.consttree", + "constantsTreeRecursive1File": "zkevm.recursive1.consttree", + "mapConstantsTreeFile": false, + "starkFile": "zkevm.prove.json", + "starkZkIn": "zkevm.proof.zkin.json", + "starkZkInC12a":"zkevm.c12a.zkin.proof.json", + "starkFileRecursive1": "zkevm.recursive1.proof.json", + "verifierFile": "zkevm.verifier.dat", + "verifierFileRecursive1": "zkevm.recursive1.verifier.dat", + "witnessFile_disabled": "zkevm.witness.wtns", + "witnessFileRecursive1": "zkevm.recursive1.witness.wtns", + "execC12aFile": "zkevm.c12a.exec", + "execRecursive1File": "zkevm.recursive1.exec", + "starkVerifierFile": "zkevm.g16.0001.zkey", + "publicStarkFile": "zkevm.public.json", + "publicFile": "public.json", + "proofFile": "proof.json", + "keccakScriptFile": "keccak_script.json", + "keccakPolsFile_DISABLED": "keccak_pols.json", + "keccakConnectionsFile": "keccak_connections.json", + "starkInfoFile": "zkevm.starkinfo.json", + "starkInfoC12aFile": "zkevm.c12a.starkinfo.json", + "starkInfoRecursive1File": "zkevm.recursive1.starkinfo.json", + "databaseURL": "postgresql://prover_user:prover_pass@zkevm-state-db:5432/prover_db", + "dbNodesTableName": "state.nodes", + "dbProgramTableName": "state.program", + "dbAsyncWrite": false, + "dbMultiWrite": true, + "dbConnectionsPool": true, + "dbNumberOfPoolConnections": 30, + "dbMetrics": true, + "dbClearCache": false, + "dbGetTree": true, + "dbReadOnly": false, + "dbMTCacheSize": 8192, + "dbProgramCacheSize": 1024, + "cleanerPollingPeriod": 600, + "requestsPersistence": 3600, + "maxExecutorThreads": 20, + "maxProverThreads": 8, + "maxStateDBThreads": 8 +} \ No newline at end of file diff --git a/test/test.keystore b/config/example.keystore similarity index 100% rename from test/test.keystore rename to config/example.keystore diff --git a/config/genesis.go b/config/genesis.go deleted file mode 100644 index c0b9c35ac3..0000000000 --- a/config/genesis.go +++ /dev/null @@ -1,423 +0,0 @@ -package config - -import ( - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/state" -) - -var commonGenesisActions = []*state.GenesisAction{ - { - Address: "0xae4bb80be56b819606589de61d5ec3b522eeb032", - Type: int(merkletree.LeafTypeNonce), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "1", - Root: "", - }, - { - Address: "0xae4bb80be56b819606589de61d5ec3b522eeb032", - Type: int(merkletree.LeafTypeCode), - StoragePosition: "", - Bytecode: "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610197565b60006020819052908152604090205481565b6100a061009b366004610197565b6100e7565b005b6002546100c29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b60025473ffffffffffffffffffffffffffffffffffffffff163314610192576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f476c6f62616c45786974526f6f744d616e616765724c323a3a7570646174654560448201527f786974526f6f743a204f4e4c595f425249444745000000000000000000000000606482015260840160405180910390fd5b600155565b6000602082840312156101a957600080fd5b503591905056fea2646970667358221220b6ba072419f510d5d5b9a55d9605786898f58415125e7e2ac3f699371fda0cbc64736f6c634300080f0033", - Key: "", - Value: "", - Root: "", - }, - { - Address: "0xae4bb80be56b819606589de61d5ec3b522eeb032", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000002", - Bytecode: "", - Key: "", - Value: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeBalance), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "100000000000000000000000", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeNonce), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "2", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeCode), - StoragePosition: "", - Bytecode: "0x608060405260043610620001075760003560e01c80635d5d326f1162000095578063bab161bf1162000060578063bab161bf1462000414578063d02103ca1462000449578063e73758811462000478578063ed6be5c914620004ac57600080fd5b80635d5d326f146200035e57806381b1c17414620003835780638624c35c14620003ca578063b7e6a7d414620003ef57600080fd5b80633ae0504711620000d65780633ae05047146200023a5780633da816821462000252578063508935f814620002885780635a64a1da14620002a157600080fd5b806322e95f2c146200010c5780632dfdf0b5146200015b5780632f3a3d5d1462000182578063318aee3d14620001b1575b600080fd5b3480156200011957600080fd5b50620001316200012b366004620027b4565b620004c3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200016857600080fd5b506200017360415481565b60405190815260200162000152565b3480156200018f57600080fd5b50604754620001319073ffffffffffffffffffffffffffffffffffffffff1681565b348015620001be57600080fd5b5062000208620001d0366004620027f0565b60456020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff90911660208301520162000152565b3480156200024757600080fd5b506200017362000566565b3480156200025f57600080fd5b5062000277620002713660046200290f565b62000640565b604051901515815260200162000152565b6200029f620002993660046200297d565b62000740565b005b348015620002ae57600080fd5b5062000173620002c036600462002a39565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e098891b81166020808401919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006060998a1b811660248501529790991b1660388201529390951b909316603c830152605082015260708082019290925282518082039092018252609001909152805191012090565b3480156200036b57600080fd5b506200029f6200037d36600462002b51565b62000d2a565b3480156200039057600080fd5b5062000131620003a236600462002c38565b60446020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620003d757600080fd5b506200029f620003e9366004620027b4565b620017d9565b348015620003fc57600080fd5b50620001316200040e366004620027b4565b62001a57565b3480156200042157600080fd5b50604254620004339063ffffffff1681565b60405163ffffffff909116815260200162000152565b3480156200045657600080fd5b50604654620001319073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200048557600080fd5b50620002776200049736600462002c38565b60436020526000908152604090205460ff1681565b348015620004b957600080fd5b5062000433600081565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166024830152825160188184030181526038909201835281519181019190912060009081526044909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b6041546000908190815b6020811015620006385781600116600103620005d057600181602081106200059c576200059c62002c52565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925062000614565b8260218260208110620005e757620005e762002c52565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b6200062160028362002cb0565b9150806200062f8162002cec565b91505062000570565b509092915050565b60008467ffffffffffffffff8416825b6020811015620007335781600116600103620006bd578681815181106200067b576200067b62002c52565b6020026020010151836040516020016200069f929190918252602082015260400190565b6040516020818303038152906040528051906020012092506200070f565b82878281518110620006d357620006d362002c52565b6020026020010151604051602001620006f6929190918252602082015260400190565b6040516020818303038152906040528051906020012092505b6200071c60028362002cb0565b9150806200072a8162002cec565b91505062000650565b5050909114949350505050565b60425463ffffffff90811690861603620007e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4272696467653a3a6272696467653a2044455354494e4154494f4e5f43414e5460448201527f5f42455f495453454c460000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600080606073ffffffffffffffffffffffffffffffffffffffff89166200089d5785341462000893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4272696467653a3a6272696467653a20414d4f554e545f444f45535f4e4f545f60448201527f4d415443485f4d53475f56414c554500000000000000000000000000000000006064820152608401620007d8565b6000915062000bb1565b73ffffffffffffffffffffffffffffffffffffffff808a1660009081526045602090815260409182902082518084019093525463ffffffff81168352640100000000900490921691810182905290156200099e576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810188905273ffffffffffffffffffffffffffffffffffffffff8b1690639dc29fac906044016020604051808303816000875af115801562000965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200098b919062002d27565b5060208101518151909450925062000baf565b8415620009b357620009b38a88888862001b20565b620009d773ffffffffffffffffffffffffffffffffffffffff8b1633308a62001f71565b899350604260009054906101000a900463ffffffff1692508973ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000a3b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000a83919081019062002dc6565b8a73ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000acf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000b17919081019062002dc6565b8b73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000b63573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b89919062002e0f565b60405160200162000b9d9392919062002e7b565b60405160208183030381529060405291505b505b7ff0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a82848a8a8a8660415460405162000bf0979695949392919062002eb8565b60405180910390a18051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e087811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608a811b82166024860152918f901b90921660388401528c901b16603c820152605081018a9052607080820193909352815180820390930183526090019052805191012062000ca49062002055565b60465473ffffffffffffffffffffffffffffffffffffffff166333d6247d62000ccc62000566565b6040518263ffffffff1660e01b815260040162000ceb91815260200190565b600060405180830381600087803b15801562000d0657600080fd5b505af115801562000d1b573d6000803e3d6000fd5b50505050505050505050505050565b63ffffffff891660009081526043602052604090205460ff161562000dac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4272696467653a3a636c61696d3a20414c52454144595f434c41494d454400006044820152606401620007d8565b6046546040805160208082018c90528183018b9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915273ffffffffffffffffffffffffffffffffffffffff9091169063257b3632906084016020604051808303816000875af115801562000e45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e6b919062002f25565b60000362000efc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4272696467653a3a636c61696d3a20474c4f42414c5f455849545f524f4f545f60448201527f444f45535f4e4f545f4d415443480000000000000000000000000000000000006064820152608401620007d8565b60425463ffffffff85811691161462000f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4272696467653a3a636c61696d3a2044455354494e4154494f4e5f4e4554574f60448201527f524b5f444f45535f4e4f545f4d415443480000000000000000000000000000006064820152608401620007d8565b60425463ffffffff16620010c9578051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200105b908b8b63ffffffff168a62000640565b620010c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b620011e6565b8051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200117e908b8b63ffffffff168b62000640565b620011e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b63ffffffff8916600090815260436020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905573ffffffffffffffffffffffffffffffffffffffff851662001357576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff851690849060405162001279919062002f3f565b60006040518083038185875af1925050503d8060008114620012b8576040519150601f19603f3d011682016040523d82523d6000602084013e620012bd565b606091505b505090508062001350576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4272696467653a3a636c61696d3a204554485f5452414e534645525f4641494c60448201527f45440000000000000000000000000000000000000000000000000000000000006064820152608401620007d8565b5062001762565b60425463ffffffff9081169087160362001394576200138e73ffffffffffffffffffffffffffffffffffffffff86168484620021ce565b62001762565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152604490935291205490915073ffffffffffffffffffffffffffffffffffffffff1680620016c1576047546000906200147f9073ffffffffffffffffffffffffffffffffffffffff168462002226565b90506000806000868060200190518101906200149c919062002f5d565b9250925092508373ffffffffffffffffffffffffffffffffffffffff16636c9452218484848d8d6040518663ffffffff1660e01b8152600401620014e595949392919062002fde565b600060405180830381600087803b1580156200150057600080fd5b505af115801562001515573d6000803e3d6000fd5b50505050836044600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808d63ffffffff1681526020018c73ffffffffffffffffffffffffffffffffffffffff16815250604560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507fccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d598c8c86604051620016af9392919063ffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff918216602084015216604082015260600190565b60405180910390a1505050506200175f565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528216906340c10f19906044016020604051808303816000875af115801562001737573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200175d919062002d27565b505b50505b6040805163ffffffff8b811682528816602082015273ffffffffffffffffffffffffffffffffffffffff87811682840152851660608201526080810184905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a150505050505050505050565b600054610100900460ff1615808015620017fa5750600054600160ff909116105b80620018165750303b15801562001816575060005460ff166001145b620018a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620007d8565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200190357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b604280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8516179055604680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905560405162001981906200275c565b604051809103906000f0801580156200199e573d6000803e3d6000fd5b50604780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055620019ee62002306565b801562001a5257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660248201526000908190603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012060475490915062001b189073ffffffffffffffffffffffffffffffffffffffff16826200244e565b949350505050565b600062001b6383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620024d292505050565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fd505accf000000000000000000000000000000000000000000000000000000001462001c38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f48657a4d617469634d657267653a3a5f7065726d69743a204e4f545f56414c4960448201527f445f43414c4c00000000000000000000000000000000000000000000000000006064820152608401620007d8565b600080808080808062001c4f896004818d6200303e565b81019062001c5e91906200306a565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001d29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f48657a4d617469634d657267653a3a5f7065726d69743a205045524d49545f4f60448201527f574e45525f4d5553545f42455f5448455f53454e4445520000000000000000006064820152608401620007d8565b73ffffffffffffffffffffffffffffffffffffffff8616301462001dd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f48657a4d617469634d657267653a3a5f7065726d69743a205350454e4445525f60448201527f4d5553545f42455f5448495300000000000000000000000000000000000000006064820152608401620007d8565b8a851462001e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f48657a4d617469634d657267653a3a5f7065726d69743a205045524d49545f4160448201527f4d4f554e545f444f45535f4e4f545f4d415443480000000000000000000000006064820152608401620007d8565b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162001f1c919062002f3f565b6000604051808303816000865af19150503d806000811462001f5b576040519150601f19603f3d011682016040523d82523d6000602084013e62001f60565b606091505b505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526200204f9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620024d9565b50505050565b80600162002066602060026200321b565b62002072919062003229565b6041541062002104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4465706f736974436f6e74726163743a5f6465706f7369743a204d45524b4c4560448201527f5f545245455f46554c4c000000000000000000000000000000000000000000006064820152608401620007d8565b60016041600082825462002119919062003243565b909155505060415460005b6020811015620021c357816001166001036200215957826001826020811062002151576200215162002c52565b015550505050565b600181602081106200216f576200216f62002c52565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250600282620021ac919062002cb0565b915080620021ba8162002cec565b91505062002124565b5062001a526200325e565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001a529084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640162001fcc565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f591505073ffffffffffffffffffffffffffffffffffffffff811662000560576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401620007d8565b600054610100900460ff166200239f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620007d8565b60005b620023b06001602062003229565b8110156200244b5760218160208110620023ce57620023ce62002c52565b015460218260208110620023e657620023e662002c52565b015460408051602081019390935282015260600160405160208183030381529060405280519060200120602182600162002421919062003243565b6020811062002434576200243462002c52565b015580620024428162002cec565b915050620023a2565b50565b6000620024cb8383306040517f3d602d80600a3d3981f3363d3d373d3d3d363d730000000000000000000000008152606093841b60148201527f5af43d82803e903d91602b57fd5bf3ff000000000000000000000000000000006028820152921b6038830152604c8201526037808220606c830152605591012090565b9392505050565b6020015190565b60006200253d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620025ec9092919063ffffffff16565b80519091501562001a5257808060200190518101906200255e919062002d27565b62001a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620007d8565b606062001b1884846000858573ffffffffffffffffffffffffffffffffffffffff85163b62002678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620007d8565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051620026a3919062002f3f565b60006040518083038185875af1925050503d8060008114620026e2576040519150601f19603f3d011682016040523d82523d6000602084013e620026e7565b606091505b5091509150620026f982828662002704565b979650505050505050565b6060831562002715575081620024cb565b825115620027265782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007d891906200328d565b61182980620032a383390190565b803563ffffffff811681146200277f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146200244b57600080fd5b80356200277f8162002784565b60008060408385031215620027c857600080fd5b620027d3836200276a565b91506020830135620027e58162002784565b809150509250929050565b6000602082840312156200280357600080fd5b8135620024cb8162002784565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002889576200288962002810565b604052919050565b600082601f830112620028a357600080fd5b8135602067ffffffffffffffff821115620028c257620028c262002810565b8160051b620028d38282016200283f565b9283528481018201928281019087851115620028ee57600080fd5b83870192505b84831015620026f957823582529183019190830190620028f4565b600080600080608085870312156200292657600080fd5b84359350602085013567ffffffffffffffff808211156200294657600080fd5b620029548883890162002891565b94506040870135915080821682146200296c57600080fd5b509396929550929360600135925050565b60008060008060008060a087890312156200299757600080fd5b8635620029a48162002784565b9550620029b4602088016200276a565b94506040870135620029c68162002784565b935060608701359250608087013567ffffffffffffffff80821115620029eb57600080fd5b818901915089601f83011262002a0057600080fd5b81358181111562002a1057600080fd5b8a602082850101111562002a2357600080fd5b6020830194508093505050509295509295509295565b60008060008060008060c0878903121562002a5357600080fd5b62002a5e876200276a565b9550602087013562002a708162002784565b945062002a80604088016200276a565b9350606087013562002a928162002784565b9598949750929560808101359460a0909101359350915050565b600067ffffffffffffffff82111562002ac95762002ac962002810565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002b0757600080fd5b813562002b1e62002b188262002aac565b6200283f565b81815284602083860101111562002b3457600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d03121562002b7257600080fd5b8a3567ffffffffffffffff8082111562002b8b57600080fd5b62002b998e838f0162002891565b9b5062002ba960208e016200276a565b9a5060408d0135995060608d0135985062002bc760808e016200276a565b975062002bd760a08e01620027a7565b965062002be760c08e016200276a565b955062002bf760e08e01620027a7565b94506101008d013593506101208d013591508082111562002c1757600080fd5b5062002c268d828e0162002af5565b9150509295989b9194979a5092959850565b60006020828403121562002c4b57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008262002ce7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002d205762002d2062002c81565b5060010190565b60006020828403121562002d3a57600080fd5b81518015158114620024cb57600080fd5b60005b8381101562002d6857818101518382015260200162002d4e565b838111156200204f5750506000910152565b600082601f83011262002d8c57600080fd5b815162002d9d62002b188262002aac565b81815284602083860101111562002db357600080fd5b62001b1882602083016020870162002d4b565b60006020828403121562002dd957600080fd5b815167ffffffffffffffff81111562002df157600080fd5b62001b188482850162002d7a565b60ff811681146200244b57600080fd5b60006020828403121562002e2257600080fd5b8151620024cb8162002dff565b6000815180845262002e4981602086016020860162002d4b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062002e90606083018662002e2f565b828103602084015262002ea4818662002e2f565b91505060ff83166040830152949350505050565b600063ffffffff808a16835273ffffffffffffffffffffffffffffffffffffffff808a166020850152818916604085015280881660608501525085608084015260e060a084015262002f0e60e084018662002e2f565b915080841660c08401525098975050505050505050565b60006020828403121562002f3857600080fd5b5051919050565b6000825162002f5381846020870162002d4b565b9190910192915050565b60008060006060848603121562002f7357600080fd5b835167ffffffffffffffff8082111562002f8c57600080fd5b62002f9a8783880162002d7a565b9450602086015191508082111562002fb157600080fd5b5062002fc08682870162002d7a565b925050604084015162002fd38162002dff565b809150509250925092565b60a08152600062002ff360a083018862002e2f565b828103602084015262003007818862002e2f565b60ff969096166040840152505073ffffffffffffffffffffffffffffffffffffffff92909216606083015260809091015292915050565b600080858511156200304f57600080fd5b838611156200305d57600080fd5b5050820193919092039150565b600080600080600080600060e0888a0312156200308657600080fd5b8735620030938162002784565b96506020880135620030a58162002784565b955060408801359450606088013593506080880135620030c58162002dff565b9699959850939692959460a0840135945060c09093013592915050565b600181815b808511156200314157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003125576200312562002c81565b808516156200313357918102915b93841c9390800290620030e7565b509250929050565b6000826200315a5750600162000560565b81620031695750600062000560565b81600181146200318257600281146200318d57620031ad565b600191505062000560565b60ff841115620031a157620031a162002c81565b50506001821b62000560565b5060208310610133831016604e8410600b8410161715620031d2575081810a62000560565b620031de8383620030e2565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003213576200321362002c81565b029392505050565b6000620024cb838362003149565b6000828210156200323e576200323e62002c81565b500390565b6000821982111562003259576200325962002c81565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b602081526000620024cb602083018462002e2f56fe60806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200013d60201b6200080a1760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b506200014c565b6001600160a01b03163b151590565b6116cd806200015c6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80636c94522111610097578063a3c573eb11610066578063a3c573eb1461021c578063a457c2d714610261578063a9059cbb14610274578063dd62ed3e1461028757600080fd5b80636c945221146101b657806370a08231146101cb57806395d89b41146102015780639dc29fac1461020957600080fd5b806323b872dd116100d357806323b872dd1461014d578063313ce56714610160578063395093511461019057806340c10f19146101a357600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b6101026102cd565b60405161010f91906111c0565b60405180910390f35b61012b61012636600461125c565b61035f565b604051901515815260200161010f565b6035545b60405190815260200161010f565b61012b61015b366004611286565b610377565b60655474010000000000000000000000000000000000000000900460ff1660405160ff909116815260200161010f565b61012b61019e36600461125c565b61039b565b61012b6101b136600461125c565b6103e7565b6101c96101c436600461139c565b610483565b005b61013f6101d9366004611431565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61010261068e565b61012b61021736600461125c565b61069d565b60655461023c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010f565b61012b61026f36600461125c565b61072b565b61012b61028236600461125c565b6107fc565b61013f610295366004611453565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102dc90611486565b80601f016020809104026020016040519081016040528092919081815260200182805461030890611486565b80156103555780601f1061032a57610100808354040283529160200191610355565b820191906000526020600020905b81548152906001019060200180831161033857829003601f168201915b5050505050905090565b60003361036d818585610826565b5060019392505050565b6000336103858582856109da565b610390858585610ab1565b506001949350505050565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061036d90829086906103e2908790611508565b610826565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f42524944474500000000000000000060448201526064015b60405180910390fd5b61047a8383610d64565b50600192915050565b600054610100900460ff16158080156104a35750600054600160ff909116105b806104bd5750303b1580156104bd575060005460ff166001145b610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610467565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105b18686610e85565b606580547fffffffffffffffffffffff00000000000000000000000000000000000000000016337fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16177401000000000000000000000000000000000000000060ff8716021790556106238383610d64565b801561068657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6060603780546102dc90611486565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f4252494447450000000000000000006044820152606401610467565b61047a8383610f26565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610467565b6103908286868403610826565b60003361036d818585610ab1565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff83166108c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661096b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610aab5781811015610a9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b610aab8484848403610826565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610b54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff8216610bf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604090205481811015610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020526040808220858503905591851681529081208054849290610cf1908490611508565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d5791815260200190565b60405180910390a3610aab565b73ffffffffffffffffffffffffffffffffffffffff8216610de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060356000828254610df39190611508565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604081208054839290610e2d908490611508565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b5050565b600054610100900460ff16610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b610e818282611110565b73ffffffffffffffffffffffffffffffffffffffff8216610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603360205260409020548181101561107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604081208383039055603580548492906110bb908490611520565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109cd565b505050565b600054610100900460ff166111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b60366111b3838261157d565b50603761110b828261157d565b600060208083528351808285015260005b818110156111ed578581018301518582016040015282016111d1565b818111156111ff576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125757600080fd5b919050565b6000806040838503121561126f57600080fd5b61127883611233565b946020939093013593505050565b60008060006060848603121561129b57600080fd5b6112a484611233565b92506112b260208501611233565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261130257600080fd5b813567ffffffffffffffff8082111561131d5761131d6112c2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611363576113636112c2565b8160405283815286602085880101111561137c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113b457600080fd5b853567ffffffffffffffff808211156113cc57600080fd5b6113d889838a016112f1565b965060208801359150808211156113ee57600080fd5b506113fb888289016112f1565b945050604086013560ff8116811461141257600080fd5b925061142060608701611233565b949793965091946080013592915050565b60006020828403121561144357600080fd5b61144c82611233565b9392505050565b6000806040838503121561146657600080fd5b61146f83611233565b915061147d60208401611233565b90509250929050565b600181811c9082168061149a57607f821691505b6020821081036114d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561151b5761151b6114d9565b500190565b600082821015611532576115326114d9565b500390565b601f82111561110b57600081815260208120601f850160051c8101602086101561155e5750805b601f850160051c820191505b818110156106865782815560010161156a565b815167ffffffffffffffff811115611597576115976112c2565b6115ab816115a58454611486565b84611537565b602080601f8311600181146115fe57600084156115c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610686565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561164b5788860151825594840194600190910190840161162c565b508582101561168757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea264697066735822122015dd8047eba7f7221e0d7792549e5a01ba1b6dfaad0c6a70dc82ef386e0c5cc464736f6c634300080f0033a264697066735822122068cb524538909c05cc5109b7664a019588dc698f1f570976efb4dd6b6aee818364736f6c634300080f0033", - Key: "", - Value: "", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002f", - Bytecode: "", - Key: "", - Value: "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000033", - Bytecode: "", - Key: "", - Value: "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000035", - Bytecode: "", - Key: "", - Value: "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000036", - Bytecode: "", - Key: "", - Value: "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003b", - Bytecode: "", - Key: "", - Value: "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000040", - Bytecode: "", - Key: "", - Value: "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000029", - Bytecode: "", - Key: "", - Value: "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002b", - Bytecode: "", - Key: "", - Value: "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002d", - Bytecode: "", - Key: "", - Value: "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000030", - Bytecode: "", - Key: "", - Value: "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000032", - Bytecode: "", - Key: "", - Value: "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000034", - Bytecode: "", - Key: "", - Value: "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000022", - Bytecode: "", - Key: "", - Value: "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000025", - Bytecode: "", - Key: "", - Value: "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002c", - Bytecode: "", - Key: "", - Value: "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000023", - Bytecode: "", - Key: "", - Value: "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000027", - Bytecode: "", - Key: "", - Value: "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000028", - Bytecode: "", - Key: "", - Value: "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000038", - Bytecode: "", - Key: "", - Value: "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003e", - Bytecode: "", - Key: "", - Value: "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000000", - Bytecode: "", - Key: "", - Value: "0x01", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000047", - Bytecode: "", - Key: "", - Value: "0x61ba0248b0986c2480181c6e76b6adeeaa962483", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003c", - Bytecode: "", - Key: "", - Value: "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003f", - Bytecode: "", - Key: "", - Value: "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003d", - Bytecode: "", - Key: "", - Value: "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000046", - Bytecode: "", - Key: "", - Value: "0xae4bb80be56b819606589de61d5ec3b522eeb032", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000003a", - Bytecode: "", - Key: "", - Value: "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002e", - Bytecode: "", - Key: "", - Value: "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000031", - Bytecode: "", - Key: "", - Value: "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000037", - Bytecode: "", - Key: "", - Value: "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000024", - Bytecode: "", - Key: "", - Value: "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000026", - Bytecode: "", - Key: "", - Value: "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000039", - Bytecode: "", - Key: "", - Value: "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000042", - Bytecode: "", - Key: "", - Value: "0x01", - Root: "", - }, - { - Address: "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x000000000000000000000000000000000000000000000000000000000000002a", - Bytecode: "", - Key: "", - Value: "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - Root: "", - }, - { - Address: "0xc949254d682d8c9ad5682521675b8f43b102aec4", - Type: int(merkletree.LeafTypeNonce), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "3", - Root: "", - }, - { - Address: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", - Type: int(merkletree.LeafTypeBalance), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "100000000000000000000000", - Root: "", - }, - { - Address: "0x61ba0248b0986c2480181c6e76b6adeeaa962483", - Type: int(merkletree.LeafTypeNonce), - StoragePosition: "", - Bytecode: "", - Key: "", - Value: "1", - Root: "", - }, - { - Address: "0x61ba0248b0986c2480181c6e76b6adeeaa962483", - Type: int(merkletree.LeafTypeCode), - StoragePosition: "", - Bytecode: "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80636c94522111610097578063a3c573eb11610066578063a3c573eb1461021c578063a457c2d714610261578063a9059cbb14610274578063dd62ed3e1461028757600080fd5b80636c945221146101b657806370a08231146101cb57806395d89b41146102015780639dc29fac1461020957600080fd5b806323b872dd116100d357806323b872dd1461014d578063313ce56714610160578063395093511461019057806340c10f19146101a357600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b6101026102cd565b60405161010f91906111c0565b60405180910390f35b61012b61012636600461125c565b61035f565b604051901515815260200161010f565b6035545b60405190815260200161010f565b61012b61015b366004611286565b610377565b60655474010000000000000000000000000000000000000000900460ff1660405160ff909116815260200161010f565b61012b61019e36600461125c565b61039b565b61012b6101b136600461125c565b6103e7565b6101c96101c436600461139c565b610483565b005b61013f6101d9366004611431565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61010261068e565b61012b61021736600461125c565b61069d565b60655461023c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010f565b61012b61026f36600461125c565b61072b565b61012b61028236600461125c565b6107fc565b61013f610295366004611453565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102dc90611486565b80601f016020809104026020016040519081016040528092919081815260200182805461030890611486565b80156103555780601f1061032a57610100808354040283529160200191610355565b820191906000526020600020905b81548152906001019060200180831161033857829003601f168201915b5050505050905090565b60003361036d818585610826565b5060019392505050565b6000336103858582856109da565b610390858585610ab1565b506001949350505050565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061036d90829086906103e2908790611508565b610826565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f42524944474500000000000000000060448201526064015b60405180910390fd5b61047a8383610d64565b50600192915050565b600054610100900460ff16158080156104a35750600054600160ff909116105b806104bd5750303b1580156104bd575060005460ff166001145b610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610467565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105b18686610e85565b606580547fffffffffffffffffffffff00000000000000000000000000000000000000000016337fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16177401000000000000000000000000000000000000000060ff8716021790556106238383610d64565b801561068657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6060603780546102dc90611486565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f4252494447450000000000000000006044820152606401610467565b61047a8383610f26565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610467565b6103908286868403610826565b60003361036d818585610ab1565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff83166108c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661096b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610aab5781811015610a9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b610aab8484848403610826565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610b54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff8216610bf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604090205481811015610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020526040808220858503905591851681529081208054849290610cf1908490611508565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d5791815260200190565b60405180910390a3610aab565b73ffffffffffffffffffffffffffffffffffffffff8216610de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060356000828254610df39190611508565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604081208054839290610e2d908490611508565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b5050565b600054610100900460ff16610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b610e818282611110565b73ffffffffffffffffffffffffffffffffffffffff8216610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603360205260409020548181101561107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604081208383039055603580548492906110bb908490611520565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109cd565b505050565b600054610100900460ff166111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b60366111b3838261157d565b50603761110b828261157d565b600060208083528351808285015260005b818110156111ed578581018301518582016040015282016111d1565b818111156111ff576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125757600080fd5b919050565b6000806040838503121561126f57600080fd5b61127883611233565b946020939093013593505050565b60008060006060848603121561129b57600080fd5b6112a484611233565b92506112b260208501611233565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261130257600080fd5b813567ffffffffffffffff8082111561131d5761131d6112c2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611363576113636112c2565b8160405283815286602085880101111561137c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113b457600080fd5b853567ffffffffffffffff808211156113cc57600080fd5b6113d889838a016112f1565b965060208801359150808211156113ee57600080fd5b506113fb888289016112f1565b945050604086013560ff8116811461141257600080fd5b925061142060608701611233565b949793965091946080013592915050565b60006020828403121561144357600080fd5b61144c82611233565b9392505050565b6000806040838503121561146657600080fd5b61146f83611233565b915061147d60208401611233565b90509250929050565b600181811c9082168061149a57607f821691505b6020821081036114d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561151b5761151b6114d9565b500190565b600082821015611532576115326114d9565b500390565b601f82111561110b57600081815260208120601f850160051c8101602086101561155e5750805b601f850160051c820191505b818110156106865782815560010161156a565b815167ffffffffffffffff811115611597576115976112c2565b6115ab816115a58454611486565b84611537565b602080601f8311600181146115fe57600084156115c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610686565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561164b5788860151825594840194600190910190840161162c565b508582101561168757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea264697066735822122015dd8047eba7f7221e0d7792549e5a01ba1b6dfaad0c6a70dc82ef386e0c5cc464736f6c634300080f0033", - Key: "", - Value: "", - Root: "", - }, - { - Address: "0x61ba0248b0986c2480181c6e76b6adeeaa962483", - Type: int(merkletree.LeafTypeStorage), - StoragePosition: "0x0000000000000000000000000000000000000000000000000000000000000000", - Bytecode: "", - Key: "", - Value: "0x01", - Root: "", - }, -} diff --git a/config/initproverdb.sql b/config/initproverdb.sql deleted file mode 100644 index 9990a42755..0000000000 --- a/config/initproverdb.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE DATABASE prover_db; -\connect prover_db; - -CREATE SCHEMA state; - -CREATE TABLE state.merkletree ( - hash BYTEA PRIMARY KEY, - data BYTEA NOT NULL -); - -CREATE USER prover_user with password 'prover_pass'; -GRANT CONNECT ON DATABASE prover_db TO prover_user; -GRANT USAGE ON SCHEMA state TO prover_user; -GRANT ALL PRIVILEGES ON TABLE state.merkletree TO prover_user; diff --git a/config/mainnetgenesis.go b/config/mainnetgenesis.go new file mode 100644 index 0000000000..a27e7b739e --- /dev/null +++ b/config/mainnetgenesis.go @@ -0,0 +1,107 @@ +package config + +// MainnetNetworkConfigJSON is the hardcoded network configuration to be used for the official mainnet setup +const MainnetNetworkConfigJSON = ` +{ + "l1Config" : { + "chainId": 1, + "polygonZkEVMAddress": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", + "maticTokenAddress": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", + "polygonZkEVMGlobalExitRootAddress": "0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb" + }, + "root": "0x3f86b09b43e3e49a41fc20a07579b79eba044253367817d5c241d23c0e2bc5c9", + "genesisBlockNumber": 16896721, + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0xCB19eDdE626906eB1EE52357a27F62dd519608C2", + "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100e65780638da5cb5b146100fb578063e11ae6cb14610126578063f2fde38b1461013957600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610927565b610159565b005b6100886100983660046109c7565b6101cb565b3480156100a957600080fd5b506100bd6100b8366004610a1e565b61020d565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b50610088610220565b34801561010757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100bd565b610088610134366004610a40565b610234565b34801561014557600080fd5b50610088610154366004610a90565b61029b565b610161610357565b600061016e8585856103d8565b905061017a8183610537565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101d3610357565b6101de83838361057b565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b600061021983836105a9565b9392505050565b610228610357565b61023260006105b6565b565b61023c610357565b60006102498484846103d8565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b6102a3610357565b73ffffffffffffffffffffffffffffffffffffffff811661034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610354816105b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610342565b600083471015610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610342565b81516000036104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610342565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610342565b6060610219838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061062b565b60606105a1848484604051806060016040528060298152602001610b3d6029913961062b565b949350505050565b6000610219838330610744565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610342565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516106e69190610acf565b60006040518083038185875af1925050503d8060008114610723576040519150601f19603f3d011682016040523d82523d6000602084013e610728565b606091505b50915091506107398783838761076e565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156108045782516000036107fd5773ffffffffffffffffffffffffffffffffffffffff85163b6107fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610342565b50816105a1565b6105a183838151156108195781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103429190610aeb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261088d57600080fd5b813567ffffffffffffffff808211156108a8576108a861084d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108ee576108ee61084d565b8160405283815286602085880101111561090757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561093d57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561096357600080fd5b61096f8883890161087c565b9350606087013591508082111561098557600080fd5b506109928782880161087c565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff811681146109c257600080fd5b919050565b6000806000606084860312156109dc57600080fd5b6109e58461099e565b9250602084013567ffffffffffffffff811115610a0157600080fd5b610a0d8682870161087c565b925050604084013590509250925092565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600080600060608486031215610a5557600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a7a57600080fd5b610a868682870161087c565b9150509250925092565b600060208284031215610aa257600080fd5b6102198261099e565b60005b83811015610ac6578181015183820152602001610aae565b50506000910152565b60008251610ae1818460208701610aab565b9190910192915050565b6020815260008251806020840152610b0a816040850160208701610aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203e70ce334e8ec9d8d03e87415afd36dce4e82633bd277b08937095a6bd66367764736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000004c1665d6651ecefa59b9b3041951608468b18891" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x0F99738B2Fc14D77308337f3e2596b63aE7BCC4A", + "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b366004610608565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb36600461062c565b610269565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610694565b6102f7565b34801561014a57600080fd5b506100de61015936600461062c565b61038c565b34801561016a57600080fd5b506100de610179366004610608565b6103e8565b34801561018a57600080fd5b506100a0610199366004610608565b6104a4565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610788565b949350505050565b61025d6104f0565b6102676000610571565b565b6102716104f0565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156102db57600080fd5b505af11580156102ef573d6000803e3d6000fd5b505050505050565b6102ff6104f0565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061035590869086906004016107a5565b6000604051808303818588803b15801561036e57600080fd5b505af1158015610382573d6000803e3d6000fd5b5050505050505050565b6103946104f0565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102c1565b6103f06104f0565b73ffffffffffffffffffffffffffffffffffffffff8116610498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104a181610571565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161048f565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146104a157600080fd5b60006020828403121561061a57600080fd5b8135610625816105e6565b9392505050565b6000806040838503121561063f57600080fd5b823561064a816105e6565b9150602083013561065a816105e6565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156106a957600080fd5b83356106b4816105e6565b925060208401356106c4816105e6565b9150604084013567ffffffffffffffff808211156106e157600080fd5b818601915086601f8301126106f557600080fd5b81358181111561070757610707610665565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561074d5761074d610665565b8160405282815289602084870101111561076657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561079a57600080fd5b8151610625816105e6565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156107ef578581018301518582016060015282016107d3565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea2646970667358221220372a0e10eebea1b7fa43ae4c976994e6ed01d85eedc3637b83f01d3f06be442064736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000bba0935fa93eb23de7990b47f0d96a8f75766d13" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0x5ac4182A1dd41AeEf465E40B82fd326BF66AB82C", + "bytecode": "0x6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000639578063ee25560b1462000651578063fb570834146200068257600080fd5b8063be5831c714620005ae578063cd58657914620005ea578063d02103ca146200060157600080fd5b80639e34070f11620000be5780639e34070f146200050a578063aaa13cc2146200054f578063bab161bf146200057457600080fd5b8063647c576c146200048657806379e2cf9714620004ab57806381b1c17414620004c357600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf2146200034b5780633ae05047146200037a5780633e197043146200039257600080fd5b80632d2c9d9414620002765780632dfdf0b5146200029b578063318aee3d14620002c257600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200023a5780632cffd02e146200025157600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed620006a7565b005b348015620001fc57600080fd5b50620002146200020e366004620032db565b62000705565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001cc565b620001ed6200024b36600462003372565b620007a8565b3480156200025e57600080fd5b50620001ed6200027036600462003409565b620009d0565b3480156200028357600080fd5b50620001ed6200029536600462003409565b62000f74565b348015620002a857600080fd5b50620002b360535481565b604051908152602001620001cc565b348015620002cf57600080fd5b5062000319620002e1366004620034ef565b606b6020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001cc565b3480156200035857600080fd5b50606c54620002149073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200038757600080fd5b50620002b362001178565b3480156200039f57600080fd5b50620002b3620003b136600462003526565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200049357600080fd5b50620001ed620004a5366004620035b0565b6200125e565b348015620004b857600080fd5b50620001ed620014ad565b348015620004d057600080fd5b5062000214620004e236600462003600565b606a6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200051757600080fd5b50620001c06200052936600462003600565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200055c57600080fd5b50620002146200056e3660046200361a565b620014e7565b3480156200058157600080fd5b506068546200059890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620005bb57600080fd5b506068546200059890790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001ed620005fb366004620036ce565b620016d3565b3480156200060e57600080fd5b50606854620002149065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200064657600080fd5b50620001ed62001c37565b3480156200065e57600080fd5b50620002b36200067036600462003600565b60696020526000908152604090205481565b3480156200068f57600080fd5b50620001c0620006a136600462003770565b62001c93565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006f9576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362001d7c565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091206000908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007e6576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8681166101009092041614806200080c5750600263ffffffff861610155b1562000844576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163388883488886053546040516200089a9998979695949392919062003806565b60405180910390a1620009b8620009b26001606860019054906101000a900463ffffffff16338989348989604051620008d592919062003881565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b62001e10565b8215620009c957620009c962001f27565b5050505050565b60685460ff161562000a0e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000a258b8b8b8b8b8b8b8b8b8b8b600062001ffc565b73ffffffffffffffffffffffffffffffffffffffff861662000b01576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a7a9190620038e6565b60006040518083038185875af1925050503d806000811462000ab9576040519150601f19603f3d011682016040523d82523d6000602084013e62000abe565b606091505b505090508062000afa576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000efc565b60685463ffffffff61010090910481169088160362000b435762000b3d73ffffffffffffffffffffffffffffffffffffffff87168585620021ed565b62000efc565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e6e576000808062000c1886880188620039fb565b92509250925060008584848460405162000c329062003292565b62000c409392919062003abd565b8190604051809103906000f590508015801562000c61573d6000803e3d6000fd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b15801562000cd757600080fd5b505af115801562000cec573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e5c95949392919062003afa565b60405180910390a15050505062000ef9565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000edf57600080fd5b505af115801562000ef4573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000fb2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000fc98b8b8b8b8b8b8b8b8b8b8b600162001ffc565b60008473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000ffc949392919062003b42565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200107f9190620038e6565b60006040518083038185875af1925050503d8060008114620010be576040519150601f19603f3d011682016040523d82523d6000602084013e620010c3565b606091505b5050905080620010ff576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562001255578083901c600116600103620011e65760338160208110620011b257620011b262003b8a565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062001213565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806200124c9062003be8565b91505062001183565b50919392505050565b600054610100900460ff16158080156200127f5750600054600160ff909116105b806200129b5750303b1580156200129b575060005460ff166001145b6200132d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200138c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905562001443620022c3565b8015620014a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff16101562000703576200070362001f27565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200157d9062003292565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620015c8908d908d908d908d908d9060200162003c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001606929160200162003c64565b604051602081830303815290604052805190602001206040516020016200168f94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff161562001711576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200171b62002366565b60685463ffffffff888116610100909204161480620017415750600263ffffffff881610155b1562001779576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060608773ffffffffffffffffffffffffffffffffffffffff8816620017df57883414620017d5576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001ad9565b341562001818576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901562001908576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac90604401600060405180830381600087803b158015620018db57600080fd5b505af1158015620018f0573d6000803e3d6000fd5b50505050806020015194508060000151935062001ad7565b85156200191d576200191d898b8989620023db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200198b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b1919062003c97565b9050620019d773ffffffffffffffffffffffffffffffffffffffff8b1633308e620028f9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801562001a45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6b919062003c97565b905062001a79828262003cb1565b6068548c9850610100900463ffffffff169650935062001a998762002959565b62001aa48c62002a71565b62001aaf8d62002b7e565b60405160200162001ac39392919062003abd565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e868860535460405162001b1b98979695949392919062003cc7565b60405180910390a162001c0f620009b2600085878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b861562001c205762001c2062001f27565b5050505062001c2e60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c89576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362002c80565b600084815b602081101562001d6e57600163ffffffff8616821c8116900362001d0a5785816020811062001ccb5762001ccb62003b8a565b60200201358260405160200162001cec929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001d59565b8186826020811062001d205762001d2062003b8a565b602002013560405160200162001d40929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d658162003be8565b91505062001c98565b50821490505b949350505050565b60685460ff161562001dba576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b80600162001e216020600262003e79565b62001e2d919062003cb1565b6053541062001e68576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060536000815462001e7b9062003be8565b9182905550905060005b602081101562001f17578082901c60011660010362001ebd57826033826020811062001eb55762001eb562003b8a565b015550505050565b6033816020811062001ed35762001ed362003b8a565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001f0e9062003be8565b91505062001e85565b5062001f2262003e87565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001fad62001178565b6040518263ffffffff1660e01b815260040162001fcc91815260200190565b600060405180830381600087803b15801562001fe757600080fd5b505af1158015620014a7573d6000803e3d6000fd5b6200200d8b63ffffffff1662002d10565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915260009165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303816000875af1158015620020b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020d6919062003c97565b90508060000362002112576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff88811661010090920416146200215c576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606854600090610100900463ffffffff166200217a5750896200217d565b508a5b620021a66200219d848c8c8c8c8c8c8c604051620008d592919062003881565b8f8f8462001c93565b620021dd576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001f229084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002d75565b600054610100900460ff166200235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6200070362002e88565b600260015403620023d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001324565b6002600155565b6000620023ec600482848662003eb6565b620023f79162003ee2565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620026765760008080808080806200245a896004818d62003eb6565b81019062002469919062003f2b565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614620024dd576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146200252d576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002567576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620026229190620038e6565b6000604051808303816000865af19150503d806000811462002661576040519150601f19603f3d011682016040523d82523d6000602084013e62002666565b606091505b50505050505050505050620009c9565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c0000000000000000000000000000000000000000000000000000000014620026f2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080808080806200270a8a6004818e62003eb6565b81019062002719919062003f86565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146200278f576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87163014620027df576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f1691620028a39190620038e6565b6000604051808303816000865af19150503d8060008114620028e2576040519150601f19603f3d011682016040523d82523d6000602084013e620028e7565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014a79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002240565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde03000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff861691620029dd9190620038e6565b600060405180830381855afa9150503d806000811462002a1a576040519150601f19603f3d011682016040523d82523d6000602084013e62002a1f565b606091505b50915091508162002a66576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d74565b62001d748162002f21565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b41000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff86169162002af59190620038e6565b600060405180830381855afa9150503d806000811462002b32576040519150601f19603f3d011682016040523d82523d6000602084013e62002b37565b606091505b50915091508162002a66576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d74565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169162002c019190620038e6565b600060405180830381855afa9150503d806000811462002c3e576040519150601f19603f3d011682016040523d82523d6000602084013e62002c43565b606091505b509150915081801562002c57575080516020145b62002c6457601262001d74565b8080602001905181019062001d74919062004012565b60018055565b60685460ff1662002cbd576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009c9576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031119092919063ffffffff16565b80519091501562001f22578080602001905181019062002dfa919062004032565b62001f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162001324565b600054610100900460ff1662002c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6060604082511062002f435781806020019051810190620007a2919062004052565b8151602003620030d35760005b60208110801562002f9b575082818151811062002f715762002f7162003b8a565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002fb6578062002fad8162003be8565b91505062002f50565b8060000362002ffa57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562003018576200301862003891565b6040519080825280601f01601f19166020018201604052801562003043576020820181803683370190505b50905060005b82811015620030cb5784818151811062003067576200306762003b8a565b602001015160f81c60f81b82828151811062003087576200308762003b8a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620030c28162003be8565b91505062003049565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d748484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051620031489190620038e6565b60006040518083038185875af1925050503d806000811462003187576040519150601f19603f3d011682016040523d82523d6000602084013e6200318c565b606091505b50915091506200319f87838387620031aa565b979650505050505050565b60608315620032455782516000036200323d5773ffffffffffffffffffffffffffffffffffffffff85163b6200323d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162001324565b508162001d74565b62001d7483838151156200325c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620013249190620040d2565b611b6680620040e883390190565b803563ffffffff811681146200310c57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620032d857600080fd5b50565b60008060408385031215620032ef57600080fd5b620032fa83620032a0565b915060208301356200330c81620032b5565b809150509250929050565b8015158114620032d857600080fd5b60008083601f8401126200333957600080fd5b50813567ffffffffffffffff8111156200335257600080fd5b6020830191508360208285010111156200336b57600080fd5b9250929050565b6000806000806000608086880312156200338b57600080fd5b6200339686620032a0565b94506020860135620033a881620032b5565b93506040860135620033ba8162003317565b9250606086013567ffffffffffffffff811115620033d757600080fd5b620033e58882890162003326565b969995985093965092949392505050565b806104008101831015620007a257600080fd5b60008060008060008060008060008060006105208c8e0312156200342c57600080fd5b620034388d8d620033f6565b9a50620034496104008d01620032a0565b99506104208c013598506104408c013597506200346a6104608d01620032a0565b96506104808c01356200347d81620032b5565b95506200348e6104a08d01620032a0565b94506104c08c0135620034a181620032b5565b93506104e08c013592506105008c013567ffffffffffffffff811115620034c757600080fd5b620034d58e828f0162003326565b915080935050809150509295989b509295989b9093969950565b6000602082840312156200350257600080fd5b81356200350f81620032b5565b9392505050565b60ff81168114620032d857600080fd5b600080600080600080600060e0888a0312156200354257600080fd5b87356200354f8162003516565b96506200355f60208901620032a0565b955060408801356200357181620032b5565b94506200358160608901620032a0565b935060808801356200359381620032b5565b9699959850939692959460a0840135945060c09093013592915050565b600080600060608486031215620035c657600080fd5b620035d184620032a0565b92506020840135620035e381620032b5565b91506040840135620035f581620032b5565b809150509250925092565b6000602082840312156200361357600080fd5b5035919050565b600080600080600080600060a0888a0312156200363657600080fd5b6200364188620032a0565b965060208801356200365381620032b5565b9550604088013567ffffffffffffffff808211156200367157600080fd5b6200367f8b838c0162003326565b909750955060608a01359150808211156200369957600080fd5b50620036a88a828b0162003326565b9094509250506080880135620036be8162003516565b8091505092959891949750929550565b600080600080600080600060c0888a031215620036ea57600080fd5b620036f588620032a0565b965060208801356200370781620032b5565b95506040880135945060608801356200372081620032b5565b93506080880135620037328162003317565b925060a088013567ffffffffffffffff8111156200374f57600080fd5b6200375d8a828b0162003326565b989b979a50959850939692959293505050565b60008060008061046085870312156200378857600080fd5b843593506200379b8660208701620033f6565b9250620037ac6104208601620032a0565b939692955092936104400135925050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620038678285018789620037bd565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811015620038dd578181015183820152602001620038c3565b50506000910152565b60008251620038fa818460208701620038c0565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200394e576200394e62003891565b604052919050565b600067ffffffffffffffff82111562003973576200397362003891565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620039b157600080fd5b8135620039c8620039c28262003956565b62003904565b818152846020838601011115620039de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562003a1157600080fd5b833567ffffffffffffffff8082111562003a2a57600080fd5b62003a38878388016200399f565b9450602086013591508082111562003a4f57600080fd5b5062003a5e868287016200399f565b9250506040840135620035f58162003516565b6000815180845262003a8b816020860160208601620038c0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062003ad2606083018662003a71565b828103602084015262003ae6818662003a71565b91505060ff83166040830152949350505050565b63ffffffff86168152600073ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200319f608083018486620037bd565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff8416602082015260606040820152600062003b80606083018486620037bd565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003c1c5762003c1c62003bb9565b5060010190565b60608152600062003c39606083018789620037bd565b828103602084015262003c4e818688620037bd565b91505060ff831660408301529695505050505050565b6000835162003c78818460208801620038c0565b83519083019062003c8e818360208801620038c0565b01949350505050565b60006020828403121562003caa57600080fd5b5051919050565b81810381811115620007a257620007a262003bb9565b600061010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003d278285018762003a71565b925080851660e085015250509998505050505050505050565b600181815b8085111562003d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d835762003d8362003bb9565b8085161562003d9157918102915b93841c939080029062003d45565b509250929050565b60008262003db857506001620007a2565b8162003dc757506000620007a2565b816001811462003de0576002811462003deb5762003e0b565b6001915050620007a2565b60ff84111562003dff5762003dff62003bb9565b50506001821b620007a2565b5060208310610133831016604e8410600b841016171562003e30575081810a620007a2565b62003e3c838362003d40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003e715762003e7162003bb9565b029392505050565b60006200350f838362003da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000808585111562003ec757600080fd5b8386111562003ed557600080fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003f235780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a03121562003f4757600080fd5b873562003f5481620032b5565b9650602088013562003f6681620032b5565b955060408801359450606088013593506080880135620035938162003516565b600080600080600080600080610100898b03121562003fa457600080fd5b883562003fb181620032b5565b9750602089013562003fc381620032b5565b96506040890135955060608901359450608089013562003fe38162003317565b935060a089013562003ff58162003516565b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156200402557600080fd5b81516200350f8162003516565b6000602082840312156200404557600080fd5b81516200350f8162003317565b6000602082840312156200406557600080fd5b815167ffffffffffffffff8111156200407d57600080fd5b8201601f810184136200408f57600080fd5b8051620040a0620039c28262003956565b818152856020838501011115620040b657600080fd5b620040c9826020830160208601620038c0565b95945050505050565b6020815260006200350f602083018462003a7156fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220d9b3ca7b13ec80ac58634ddf0ecebe71e209a71f532614949b9e720413f50c8364736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "200000000000000000000000000", + "nonce": "1", + "address": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe", + "bytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461088b565b610135565b61006b6100a33660046108a6565b61017f565b3480156100b457600080fd5b506100bd6101f3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461088b565b610231565b34801561011257600080fd5b506100bd61025e565b6101236102d4565b61013361012e6103ab565b6103b5565b565b61013d6103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481604051806020016040528060008152506000610419565b50565b61017461011b565b6101876103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101eb576101e68383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610419915050565b505050565b6101e661011b565b60006101fd6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103ab565b905090565b61022e61011b565b90565b6102396103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481610444565b60006102686103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103d9565b60606102b183836040518060600160405280602781526020016109bb602791396104a5565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6102dc6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061022161052a565b3660008037600080366000845af43d6000803e8080156103d4573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b61042283610552565b60008251118061042f5750805b156101e65761043e838361028c565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61046d6103d9565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16101748161059f565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516104cf919061094d565b600060405180830381855af49150503d806000811461050a576040519150601f19603f3d011682016040523d82523d6000602084013e61050f565b606091505b5091509150610520868383876106ab565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103fd565b61055b81610753565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a2565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6060831561074157825160000361073a5773ffffffffffffffffffffffffffffffffffffffff85163b61073a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a2565b508161074b565b61074b838361081e565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81163b6107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016103a2565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610665565b81511561082e5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a29190610969565b803573ffffffffffffffffffffffffffffffffffffffff8116811461088657600080fd5b919050565b60006020828403121561089d57600080fd5b6102b182610862565b6000806000604084860312156108bb57600080fd5b6108c484610862565b9250602084013567ffffffffffffffff808211156108e157600080fd5b818601915086601f8301126108f557600080fd5b81358181111561090457600080fd5b87602082850101111561091657600080fd5b6020830194508093505050509250925092565b60005b8381101561094457818101518382015260200161092c565b50506000910152565b6000825161095f818460208701610929565b9190910192915050565b6020815260008251806020840152610988816040850160208701610929565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a1af0d6cb4f1e31496a4c5c1448913bce4bd6ad3a39e47c6f7190c114d6f9bf464736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000068": "0x00000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa0000000100", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000005ac4182a1dd41aeef465e40b82fd326bf66ab82c" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x0200143Fa295EE4dffEF22eE2616c2E008D81688", + "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610162565b60006020819052908152604090205481565b6100a061009b366004610162565b6100ee565b005b6100c97f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede161461015d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b60006020828403121561017457600080fd5b503591905056fea2646970667358221220a187fc278346c1b61c449ea3641002b6eac2bda3351a122a12c35099f933696864736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106ca565b610118565b61005b6100933660046106e5565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106ca565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103f1565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107e460279139610445565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb610519565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b83610541565b6040516001600160a01b038416907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000825111806103dc5750805b156101c3576103eb8383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a61035f565b604080516001600160a01b03928316815291841660208301520160405180910390a1610154816105e9565b6060833b6104a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b0316856040516104bf9190610794565b600060405180830381855af49150503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b509150915061050f828286610675565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b803b6105a55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b03811661064e5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036105c8565b60608315610684575081610285565b8251156106945782518084602001fd5b8160405162461bcd60e51b815260040161032891906107b0565b80356001600160a01b03811681146106c557600080fd5b919050565b6000602082840312156106dc57600080fd5b610285826106ae565b6000806000604084860312156106fa57600080fd5b610703846106ae565b9250602084013567ffffffffffffffff8082111561072057600080fd5b818601915086601f83011261073457600080fd5b81358181111561074357600080fd5b87602082850101111561075557600080fd5b6020830194508093505050509250925092565b60005b8381101561078357818101518382015260200161076b565b838111156103eb5750506000910152565b600082516107a6818460208701610768565b9190910192915050565b60208152600082518060208401526107cf816040850160208701610768565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204675187caf3a43285d9a2c1844a981e977bd52a85ff073e7fc649f73847d70a464736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000000200143fa295ee4dffef22ee2616c2e008d81688" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0xBBa0935Fa93Eb23de7990b47F0D96a8f75766d13", + "bytecode": "0x6080604052600436106101c65760003560e01c806364d62353116100f7578063b1c5f42711610095578063d547741f11610064578063d547741f14610661578063e38335e514610681578063f23a6e6114610694578063f27a0c92146106d957600080fd5b8063b1c5f427146105af578063bc197c81146105cf578063c4d252f514610614578063d45c44351461063457600080fd5b80638f61f4f5116100d15780638f61f4f5146104e157806391d1485414610515578063a217fddf14610566578063b08e51c01461057b57600080fd5b806364d62353146104815780638065657f146104a15780638f2a0bb0146104c157600080fd5b8063248a9ca31161016457806331d507501161013e57806331d50750146103c857806336568abe146103e85780633a6aae7214610408578063584b153e1461046157600080fd5b8063248a9ca3146103475780632ab0f529146103775780632f2ff15d146103a857600080fd5b80630d3cf6fc116101a05780630d3cf6fc1461026b578063134008d31461029f57806313bc9f20146102b2578063150b7a02146102d257600080fd5b806301d5062a146101d257806301ffc9a7146101f457806307bd02651461022957600080fd5b366101cd57005b600080fd5b3480156101de57600080fd5b506101f26101ed366004611c52565b6106ee565b005b34801561020057600080fd5b5061021461020f366004611cc7565b610783565b60405190151581526020015b60405180910390f35b34801561023557600080fd5b5061025d7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610220565b34801561027757600080fd5b5061025d7f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101f26102ad366004611d09565b6107df565b3480156102be57600080fd5b506102146102cd366004611d75565b6108d7565b3480156102de57600080fd5b506103166102ed366004611e9a565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610220565b34801561035357600080fd5b5061025d610362366004611d75565b60009081526020819052604090206001015490565b34801561038357600080fd5b50610214610392366004611d75565b6000908152600160208190526040909120541490565b3480156103b457600080fd5b506101f26103c3366004611f02565b6108fd565b3480156103d457600080fd5b506102146103e3366004611d75565b610927565b3480156103f457600080fd5b506101f2610403366004611f02565b610940565b34801561041457600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610220565b34801561046d57600080fd5b5061021461047c366004611d75565b6109f8565b34801561048d57600080fd5b506101f261049c366004611d75565b610a0e565b3480156104ad57600080fd5b5061025d6104bc366004611d09565b610ade565b3480156104cd57600080fd5b506101f26104dc366004611f73565b610b1d565b3480156104ed57600080fd5b5061025d7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561052157600080fd5b50610214610530366004611f02565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561057257600080fd5b5061025d600081565b34801561058757600080fd5b5061025d7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156105bb57600080fd5b5061025d6105ca366004612025565b610d4f565b3480156105db57600080fd5b506103166105ea36600461214e565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b34801561062057600080fd5b506101f261062f366004611d75565b610d94565b34801561064057600080fd5b5061025d61064f366004611d75565b60009081526001602052604090205490565b34801561066d57600080fd5b506101f261067c366004611f02565b610e8f565b6101f261068f366004612025565b610eb4565b3480156106a057600080fd5b506103166106af3660046121f8565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106e557600080fd5b5061025d611161565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161071881611244565b6000610728898989898989610ade565b90506107348184611251565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a604051610770969594939291906122a6565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107d957506107d98261139e565b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661085c5761085c8133611435565b600061086c888888888888610ade565b905061087881856114ed565b6108848888888861162a565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516108bc94939291906122f1565b60405180910390a36108cd8161172e565b5050505050505050565b6000818152600160205260408120546001811180156108f65750428111155b9392505050565b60008281526020819052604090206001015461091881611244565b61092283836117d7565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109f482826118c7565b5050565b6000818152600160208190526040822054610939565b333014610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109e1565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610afb969594939291906122a6565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b4781611244565b888714610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b888514610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b6000610c778b8b8b8b8b8b8b8b610d4f565b9050610c838184611251565b60005b8a811015610d415780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610cc357610cc3612331565b9050602002016020810190610cd89190612360565b8d8d86818110610cea57610cea612331565b905060200201358c8c87818110610d0357610d03612331565b9050602002810190610d15919061237b565b8c8b604051610d29969594939291906122a6565b60405180910390a3610d3a8161240f565b9050610c86565b505050505050505050505050565b60008888888888888888604051602001610d709897969594939291906124f7565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610dbe81611244565b610dc7826109f8565b610e53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109e1565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610eaa81611244565b61092283836118c7565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610f3157610f318133611435565b878614610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b87841461104f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b60006110618a8a8a8a8a8a8a8a610d4f565b905061106d81856114ed565b60005b8981101561114b5760008b8b8381811061108c5761108c612331565b90506020020160208101906110a19190612360565b905060008a8a848181106110b7576110b7612331565b9050602002013590503660008a8a868181106110d5576110d5612331565b90506020028101906110e7919061237b565b915091506110f78484848461162a565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161112e94939291906122f1565b60405180910390a350505050806111449061240f565b9050611070565b506111558161172e565b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580159061123257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123291906125be565b1561123d5750600090565b5060025490565b61124e8133611435565b50565b61125a82610927565b156112e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109e1565b6112ef611161565b81101561137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109e1565b61138881426125e0565b6000928352600160205260409092209190915550565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107d957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107d9565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f4576114738161197e565b61147e83602061199d565b60405160200161148f929190612617565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109e191600401612698565b6114f6826108d7565b611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b80158061159e5750600081815260016020819052604090912054145b6109f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109e1565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516116549291906126e9565b60006040518083038185875af1925050503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b5050905080611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109e1565b5050505050565b611737816108d7565b6117c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556118693390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107d973ffffffffffffffffffffffffffffffffffffffff831660145b606060006119ac8360026126f9565b6119b79060026125e0565b67ffffffffffffffff8111156119cf576119cf611d8e565b6040519080825280601f01601f1916602001820160405280156119f9576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611a3057611a30612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a9357611a93612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000611acf8460026126f9565b611ada9060016125e0565b90505b6001811115611b77577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611b1b57611b1b612331565b1a60f81b828281518110611b3157611b31612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93611b7081612710565b9050611add565b5083156108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109e1565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c0457600080fd5b919050565b60008083601f840112611c1b57600080fd5b50813567ffffffffffffffff811115611c3357600080fd5b602083019150836020828501011115611c4b57600080fd5b9250929050565b600080600080600080600060c0888a031215611c6d57600080fd5b611c7688611be0565b965060208801359550604088013567ffffffffffffffff811115611c9957600080fd5b611ca58a828b01611c09565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611cd957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108f657600080fd5b60008060008060008060a08789031215611d2257600080fd5b611d2b87611be0565b955060208701359450604087013567ffffffffffffffff811115611d4e57600080fd5b611d5a89828a01611c09565b979a9699509760608101359660809091013595509350505050565b600060208284031215611d8757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e0457611e04611d8e565b604052919050565b600082601f830112611e1d57600080fd5b813567ffffffffffffffff811115611e3757611e37611d8e565b611e6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611dbd565b818152846020838601011115611e7d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611eb057600080fd5b611eb985611be0565b9350611ec760208601611be0565b925060408501359150606085013567ffffffffffffffff811115611eea57600080fd5b611ef687828801611e0c565b91505092959194509250565b60008060408385031215611f1557600080fd5b82359150611f2560208401611be0565b90509250929050565b60008083601f840112611f4057600080fd5b50813567ffffffffffffffff811115611f5857600080fd5b6020830191508360208260051b8501011115611c4b57600080fd5b600080600080600080600080600060c08a8c031215611f9157600080fd5b893567ffffffffffffffff80821115611fa957600080fd5b611fb58d838e01611f2e565b909b50995060208c0135915080821115611fce57600080fd5b611fda8d838e01611f2e565b909950975060408c0135915080821115611ff357600080fd5b506120008c828d01611f2e565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b03121561204157600080fd5b883567ffffffffffffffff8082111561205957600080fd5b6120658c838d01611f2e565b909a50985060208b013591508082111561207e57600080fd5b61208a8c838d01611f2e565b909850965060408b01359150808211156120a357600080fd5b506120b08b828c01611f2e565b999c989b509699959896976060870135966080013595509350505050565b600082601f8301126120df57600080fd5b8135602067ffffffffffffffff8211156120fb576120fb611d8e565b8160051b61210a828201611dbd565b928352848101820192828101908785111561212457600080fd5b83870192505b848310156121435782358252918301919083019061212a565b979650505050505050565b600080600080600060a0868803121561216657600080fd5b61216f86611be0565b945061217d60208701611be0565b9350604086013567ffffffffffffffff8082111561219a57600080fd5b6121a689838a016120ce565b945060608801359150808211156121bc57600080fd5b6121c889838a016120ce565b935060808801359150808211156121de57600080fd5b506121eb88828901611e0c565b9150509295509295909350565b600080600080600060a0868803121561221057600080fd5b61221986611be0565b945061222760208701611be0565b93506040860135925060608601359150608086013567ffffffffffffffff81111561225157600080fd5b6121eb88828901611e0c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a0604082015260006122dc60a08301868861225d565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061232760608301848661225d565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561237257600080fd5b6108f682611be0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126123b057600080fd5b83018035915067ffffffffffffffff8211156123cb57600080fd5b602001915036819003821315611c4b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612440576124406123e0565b5060010190565b81835260006020808501808196508560051b810191508460005b878110156124ea57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126124a057600080fd5b8701858101903567ffffffffffffffff8111156124bc57600080fd5b8036038213156124cb57600080fd5b6124d686828461225d565b9a87019a9550505090840190600101612461565b5091979650505050505050565b60a0808252810188905260008960c08301825b8b8110156125455773ffffffffffffffffffffffffffffffffffffffff61253084611be0565b1682526020928301929091019060010161250a565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89111561257e57600080fd5b8860051b9150818a602083013701828103602090810160408501526125a69082018789612447565b60608401959095525050608001529695505050505050565b6000602082840312156125d057600080fd5b815180151581146108f657600080fd5b808201808211156107d9576107d96123e0565b60005b8381101561260e5781810151838201526020016125f6565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161264f8160178501602088016125f3565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161268c8160288401602088016125f3565b01602801949350505050565b60208152600082518060208401526126b78160408501602087016125f3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b8183823760009101908152919050565b80820281158282048414176107d9576107d96123e0565b60008161271f5761271f6123e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212206416c4e08f97752b4bb06159524dac058d3dccd8775e57ef1b01505751ebf7af64736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000d2f00", + "0x33d4aa03df3f12c4f615b40676f67fdafecd3edb5a9c0ca2a47a923dae33a023": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9fa2d8034dbcb437bee38d61fbd100910e1342ffc07f128aa1b8e6790b7f3f68": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x531a7c25761aa4b0f2310edca9bb25e1e3ceb49ad4b0422aec866b3ce7567c87": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0xedbedc78c4240c7613622a35de050b48bd6c6d9a31b3d485b68fbbed54a4802d": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x76616448da8d124a07383c26a6b2433b3259de946aa40f51524ec96ee05e871a": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x9d90066e7478496e2284E54c3548106bb4F90E50" + }, + { + "accountName": "deployer", + "balance": "0", + "nonce": "8", + "address": "0x4c1665d6651ecEfa59B9B3041951608468b18891" + } + ] + } +` diff --git a/config/metrics/prometheus/prometheus.yml b/config/metrics/prometheus/prometheus.yml new file mode 100644 index 0000000000..583d9370ea --- /dev/null +++ b/config/metrics/prometheus/prometheus.yml @@ -0,0 +1,14 @@ +global: + scrape_interval: 3s # By default, scrape targets every 15 seconds. + evaluation_interval: 3s # By default, scrape targets every 15 seconds. + # scrape_timeout is set to the global default (10s). + +scrape_configs: + + - job_name: zkevm-node + scrape_interval: 3s + metrics_path: /metrics + static_configs: + - targets: + - zkevm-json-rpc:9091 #inside port of the zkevm-json-rpc + - zkevm-sequencer:9091 #inside port of the zkevm-sequencer \ No newline at end of file diff --git a/config/network.go b/config/network.go index 8bee078328..6b1ea4635a 100644 --- a/config/network.go +++ b/config/network.go @@ -2,49 +2,39 @@ package config import ( "encoding/json" - "io/ioutil" + "errors" + "fmt" + "io" "os" - "reflect" + "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" - "github.com/imdario/mergo" "github.com/urfave/cli/v2" ) // NetworkConfig is the configuration struct for the different environments type NetworkConfig struct { - GenBlockNumber uint64 - PoEAddr common.Address - MaticAddr common.Address - L2GlobalExitRootManagerAddr common.Address - L2BridgeAddr common.Address - GlobalExitRootManagerAddr common.Address - SystemSCAddr common.Address - GlobalExitRootStoragePosition uint64 - LocalExitRootStoragePosition uint64 - OldStateRootPosition uint64 - L1ChainID uint64 - // L2ChainID is read from POE SC - L2ChainID uint64 - Genesis state.Genesis - MaxCumulativeGasUsed uint64 + L1Config etherman.L1Config `json:"l1Config"` + L2GlobalExitRootManagerAddr common.Address + L2BridgeAddr common.Address + Genesis state.Genesis + MaxCumulativeGasUsed uint64 } -type networkConfigFromJSON struct { - PoEAddr string `json:"proofOfEfficiencyAddress"` - MaticAddr string `json:"maticTokenAddress"` - GlobalExitRootManagerAddr string `json:"globalExitRootManagerAddress"` - GenBlockNumber uint64 `json:"deploymentBlockNumber"` - SystemSCAddr string `json:"systemSCAddr"` - GlobalExitRootStoragePosition uint64 `json:"globalExitRootStoragePosition"` - LocalExitRootStoragePosition uint64 `json:"localExitRootStoragePosition"` - OldStateRootPosition uint64 `json:"oldStateRootPosition"` - L1ChainID uint64 `json:"l1ChainID"` - Root string `json:"root"` - Genesis []genesisAccountFromJSON `json:"genesis"` +type network string + +const mainnet network = "mainnet" +const testnet network = "testnet" +const custom network = "custom" + +type genesisFromJSON struct { + Root string `json:"root"` + GenesisBlockNum uint64 `json:"genesisBlockNumber"` + Genesis []genesisAccountFromJSON `json:"genesis"` + L1Config etherman.L1Config } type genesisAccountFromJSON struct { @@ -56,220 +46,74 @@ type genesisAccountFromJSON struct { ContractName string `json:"contractName"` } -const ( - testnet = "testnet" - internalTestnet = "internaltestnet" - local = "local" - merge = "merge" - custom = "custom" -) - -//nolint:gomnd -var ( - mainnetConfig = NetworkConfig{ - GenBlockNumber: 13808430, - PoEAddr: common.HexToAddress("0x11D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FA"), - MaticAddr: common.HexToAddress("0x37AffAf737C3683aB73F6E1B0933b725Ab9796Aa"), - L2GlobalExitRootManagerAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - L2BridgeAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootManagerAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - SystemSCAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootStoragePosition: 0, - LocalExitRootStoragePosition: 1, - OldStateRootPosition: 0, - L1ChainID: 1, //Mainnet - Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FA", - Type: int(merkletree.LeafTypeBalance), - Value: "1000", - }, - { - Address: "0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FB", - Type: int(merkletree.LeafTypeBalance), - Value: "2000", - }, - }, - }, - } - testnetConfig = NetworkConfig{ - GenBlockNumber: 9817974, - PoEAddr: common.HexToAddress("0x21D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FA"), - MaticAddr: common.HexToAddress("0x37AffAf737C3683aB73F6E1B0933b725Ab9796Aa"), - L2GlobalExitRootManagerAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - L2BridgeAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootManagerAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - SystemSCAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootStoragePosition: 0, - LocalExitRootStoragePosition: 1, - OldStateRootPosition: 0, - L1ChainID: 4, //Rinkeby - Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FA", - Type: int(merkletree.LeafTypeBalance), - Value: "1000", - }, - { - Address: "0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FB", - Type: int(merkletree.LeafTypeBalance), - Value: "2000", - }, - }, - }, - } - - internalTestnetConfig = NetworkConfig{ - GenBlockNumber: 7674348, - PoEAddr: common.HexToAddress("0x159113e5560c9CC2d8c4e716228CCf92c72E9603"), - MaticAddr: common.HexToAddress("0x94Ca2BbE1b469f25D3B22BDf17Fc80ad09E7F662"), - L2GlobalExitRootManagerAddr: common.HexToAddress("0xae4bb80be56b819606589de61d5ec3b522eeb032"), - L2BridgeAddr: common.HexToAddress("0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988"), - GlobalExitRootManagerAddr: common.HexToAddress("0xA379Dd55Eb12e8FCdb467A814A15DE2b29677066"), - SystemSCAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootStoragePosition: 0, - LocalExitRootStoragePosition: 1, - OldStateRootPosition: 0, - L1ChainID: 5, //Goerli - Genesis: state.Genesis{ - Root: common.HexToHash("0xb33635210b9f5d07769cf70bf5a3cbf241ecbaf79a9b66ef79b28d920da1f776"), - Actions: []*state.GenesisAction{ - { - Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - Type: int(merkletree.LeafTypeBalance), - Value: "100000000000000000000000", - }, - }, - }, - } - - localConfig = NetworkConfig{ - GenBlockNumber: 1, - PoEAddr: common.HexToAddress("0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"), - MaticAddr: common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3"), - L2GlobalExitRootManagerAddr: common.HexToAddress("0xae4bb80be56b819606589de61d5ec3b522eeb032"), - L2BridgeAddr: common.HexToAddress("0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988"), - GlobalExitRootManagerAddr: common.HexToAddress("0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"), - SystemSCAddr: common.HexToAddress("0x0000000000000000000000000000000000000000"), - GlobalExitRootStoragePosition: 0, - LocalExitRootStoragePosition: 1, - OldStateRootPosition: 0, - L1ChainID: 1337, - Genesis: state.Genesis{ - Root: common.HexToHash("0x5e3d5372166e22ee23b4800aecb491de96f425aa5c7d56f35c96905cc5e12cb8"), - Actions: []*state.GenesisAction{ - { - Address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - Type: int(merkletree.LeafTypeBalance), - Value: "100000000000000000000000", - }, - { - Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - Type: int(merkletree.LeafTypeBalance), - Value: "100000000000000000000000", - }, - }, - }, - } - - networkConfigByName = map[string]NetworkConfig{ - testnet: testnetConfig, - internalTestnet: internalTestnetConfig, - local: localConfig, - } -) - func (cfg *Config) loadNetworkConfig(ctx *cli.Context) { - network := ctx.String(FlagNetwork) - - switch network { - case testnet: - log.Debug("Testnet network selected") - cfg.NetworkConfig = testnetConfig - case internalTestnet: - log.Debug("InternalTestnet network selected") - internalTestnetConfig.Genesis.Actions = append(internalTestnetConfig.Genesis.Actions, commonGenesisActions...) - cfg.NetworkConfig = internalTestnetConfig - case local: - log.Debug("Local network selected") - localConfig.Genesis.Actions = append(localConfig.Genesis.Actions, commonGenesisActions...) - cfg.NetworkConfig = localConfig - case custom: - customNetworkConfig, err := loadCustomNetworkConfig(ctx) - if err != nil { - log.Fatalf("Failed to load custom network configuration, err:", err) - } - cfg.NetworkConfig = customNetworkConfig - case merge: - customNetworkConfig, err := loadCustomNetworkConfig(ctx) - if err != nil { - log.Fatalf("Failed to load custom network configuration, err:", err) - } - baseNetworkConfigName := ctx.String(FlagNetworkBase) - baseNetworkConfig, ok := networkConfigByName[baseNetworkConfigName] - if !ok { - log.Fatalf("Base network configuration %q not found:", baseNetworkConfigName) - } - mergedNetworkConfig, err := mergeNetworkConfigs(customNetworkConfig, baseNetworkConfig) + var networkJSON string + switch ctx.String(FlagNetwork) { + case string(mainnet): + networkJSON = MainnetNetworkConfigJSON + case string(testnet): + networkJSON = TestnetNetworkConfigJSON + case string(custom): + var err error + networkJSON, err = loadGenesisFileAsString(ctx) if err != nil { - log.Fatalf("Failed to merge network configurations network configuration, err:", err) + panic(err.Error()) } - cfg.NetworkConfig = mergedNetworkConfig default: - log.Debug("Mainnet network selected") - cfg.NetworkConfig = mainnetConfig + panic(fmt.Errorf("unsupported --network value. Must be one of: [%s, %s, %s]", mainnet, testnet, custom)) } -} - -func loadCustomNetworkConfig(ctx *cli.Context) (NetworkConfig, error) { - cfgPath := ctx.String(FlagNetworkCfg) - - f, err := os.Open(cfgPath) //nolint:gosec + config, err := loadGenesisFromJSONString(networkJSON) if err != nil { - return NetworkConfig{}, err + panic(fmt.Errorf("failed to load genesis configuration from file. Error: %v", err)) } - defer func() { - err := f.Close() + cfg.NetworkConfig = config +} + +func loadGenesisFileAsString(ctx *cli.Context) (string, error) { + cfgPath := ctx.String(FlagCustomNetwork) + if cfgPath != "" { + f, err := os.Open(cfgPath) //nolint:gosec if err != nil { - log.Error(err) + return "", err } - }() + defer func() { + err := f.Close() + if err != nil { + log.Error(err) + } + }() - b, err := ioutil.ReadAll(f) - if err != nil { - return NetworkConfig{}, err + b, err := io.ReadAll(f) + if err != nil { + return "", err + } + return string(b), nil + } else { + return "", errors.New("custom netwrork file not provided. Please use the custom-network-file flag") } +} - var cfgJSON networkConfigFromJSON - err = json.Unmarshal([]byte(b), &cfgJSON) - if err != nil { +func loadGenesisFromJSONString(jsonStr string) (NetworkConfig, error) { + var cfg NetworkConfig + + var cfgJSON genesisFromJSON + if err := json.Unmarshal([]byte(jsonStr), &cfgJSON); err != nil { return NetworkConfig{}, err } - var cfg NetworkConfig - cfg.GenBlockNumber = cfgJSON.GenBlockNumber - cfg.PoEAddr = common.HexToAddress(cfgJSON.PoEAddr) - cfg.MaticAddr = common.HexToAddress(cfgJSON.MaticAddr) - cfg.GlobalExitRootManagerAddr = common.HexToAddress(cfgJSON.GlobalExitRootManagerAddr) - cfg.SystemSCAddr = common.HexToAddress(cfgJSON.SystemSCAddr) - cfg.GlobalExitRootStoragePosition = cfgJSON.GlobalExitRootStoragePosition - cfg.LocalExitRootStoragePosition = cfgJSON.LocalExitRootStoragePosition - cfg.OldStateRootPosition = cfgJSON.OldStateRootPosition - cfg.L1ChainID = cfgJSON.L1ChainID - if len(cfgJSON.Genesis) == 0 { return cfg, nil } + cfg.L1Config = cfgJSON.L1Config cfg.Genesis = state.Genesis{ - Root: common.HexToHash(cfgJSON.Root), - Actions: []*state.GenesisAction{}, + GenesisBlockNum: cfgJSON.GenesisBlockNum, + Root: common.HexToHash(cfgJSON.Root), + GenesisActions: []*state.GenesisAction{}, } - const l2GlobalExitRootManagerSCName = "GlobalExitRootManagerL2" - const l2BridgeSCName = "Bridge" + const l2GlobalExitRootManagerSCName = "PolygonZkEVMGlobalExitRootL2 proxy" + const l2BridgeSCName = "PolygonZkEVMBridge proxy" for _, account := range cfgJSON.Genesis { if account.ContractName == l2GlobalExitRootManagerSCName { @@ -284,7 +128,7 @@ func loadCustomNetworkConfig(ctx *cli.Context) (NetworkConfig, error) { Type: int(merkletree.LeafTypeBalance), Value: account.Balance, } - cfg.Genesis.Actions = append(cfg.Genesis.Actions, action) + cfg.Genesis.GenesisActions = append(cfg.Genesis.GenesisActions, action) } if account.Nonce != "" && account.Nonce != "0" { action := &state.GenesisAction{ @@ -292,7 +136,7 @@ func loadCustomNetworkConfig(ctx *cli.Context) (NetworkConfig, error) { Type: int(merkletree.LeafTypeNonce), Value: account.Nonce, } - cfg.Genesis.Actions = append(cfg.Genesis.Actions, action) + cfg.Genesis.GenesisActions = append(cfg.Genesis.GenesisActions, action) } if account.Bytecode != "" { action := &state.GenesisAction{ @@ -300,7 +144,7 @@ func loadCustomNetworkConfig(ctx *cli.Context) (NetworkConfig, error) { Type: int(merkletree.LeafTypeCode), Bytecode: account.Bytecode, } - cfg.Genesis.Actions = append(cfg.Genesis.Actions, action) + cfg.Genesis.GenesisActions = append(cfg.Genesis.GenesisActions, action) } if len(account.Storage) > 0 { for storageKey, storageValue := range account.Storage { @@ -310,40 +154,10 @@ func loadCustomNetworkConfig(ctx *cli.Context) (NetworkConfig, error) { StoragePosition: storageKey, Value: storageValue, } - cfg.Genesis.Actions = append(cfg.Genesis.Actions, action) + cfg.Genesis.GenesisActions = append(cfg.Genesis.GenesisActions, action) } } } - return cfg, nil -} - -type addressTransformer struct{} - -func (a addressTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ != reflect.TypeOf(common.Address{}) { - return nil - } - return func(dst, src reflect.Value) error { - if !dst.CanSet() { - return nil - } - hex := src.MethodByName("Hex") - result := hex.Call([]reflect.Value{}) - if result[0].Interface().(string) != "0x0000000000000000000000000000000000000000" { - dst.Set(src) - } - return nil - } -} -func mergeNetworkConfigs(custom, base NetworkConfig) (NetworkConfig, error) { - actionsBack := append(base.Genesis.Actions, custom.Genesis.Actions...) - - if err := mergo.MergeWithOverwrite(&base, custom, mergo.WithTransformers(addressTransformer{})); err != nil { - return NetworkConfig{}, err - } - - base.Genesis.Actions = actionsBack - - return base, nil + return cfg, nil } diff --git a/config/network_test.go b/config/network_test.go index cb68536ce0..2f062654df 100644 --- a/config/network_test.go +++ b/config/network_test.go @@ -2,13 +2,12 @@ package config import ( "flag" - "io/ioutil" "os" "testing" + "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/merkletree" "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/testutils" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" @@ -19,74 +18,70 @@ func TestLoadCustomNetworkConfig(t *testing.T) { description string inputConfigStr string expectedConfig NetworkConfig - expectedError bool expectedErrorMsg string }{ { description: "happy path", inputConfigStr: `{ - "deploymentBlockNumber": 6934972, - "proofOfEfficiencyAddress": "0x2f612dc8fB986E7976AEfc13d8bB0Eb18488a4C9", - "maticTokenAddress": "0xEa2f9aC0cd926C92923355e88Af73Ee83F2D9C67", - "globalExitRootManagerAddress": "0x9730d4ec6684E5567fB70B12d49Bf3f58f5ce4Cc", - - "globalExitRootStoragePosition": 0, - "localExitRootStoragePosition": 1, - "oldStateRootPosition": 0, - "l1ChainID": 5, - - "genesis": [ - { - "balance": "0", - "nonce": "2", - "address": "0xc949254d682d8c9ad5682521675b8f43b102aec4" - }, - { - "balance": "0", - "nonce": "1", - "address": "0xae4bb80be56b819606589de61d5ec3b522eeb032", - "bytecode": "0xbeef1", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988" - }, - "contractName": "GlobalExitRootManagerL2" - }, - { - "balance": "100000000000000000000000", - "nonce": "2", - "address": "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", - "bytecode": "0xbeef2", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0xc949254d682d8c9ad5682521675b8f43b102aec4" - }, - "contractName": "Bridge" - }, - { - "balance": "0", - "nonce": "1", - "address": "0x61ba0248b0986c2480181c6e76b6adeeaa962483", - "bytecode": "0xbeef3", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01" - } - } - ], - "maxCumulativeGasUsed": 300000 -}`, + "root": "0xBEEF", + "genesisBlockNumber": 69, + "l1Config" : { + "chainId": 420, + "polygonZkEVMAddress": "0xc949254d682d8c9ad5682521675b8f43b102aec4", + "maticTokenAddress": "0xc949254d682d8c9ad5682521675b8f43b102aec4", + "polygonZkEVMGlobalExitRootAddress": "0xc949254d682d8c9ad5682521675b8f43b102aec4" + }, + "genesis": [ + { + "balance": "0", + "nonce": "2", + "address": "0xc949254d682d8c9ad5682521675b8f43b102aec4" + }, + { + "balance": "0", + "nonce": "1", + "address": "0xae4bb80be56b819606589de61d5ec3b522eeb032", + "bytecode": "0xbeef1", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988" + }, + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy" + }, + { + "balance": "100000000000000000000000", + "nonce": "2", + "address": "0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988", + "bytecode": "0xbeef2", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0xc949254d682d8c9ad5682521675b8f43b102aec4" + }, + "contractName": "PolygonZkEVMBridge proxy" + }, + { + "balance": "0", + "nonce": "1", + "address": "0x61ba0248b0986c2480181c6e76b6adeeaa962483", + "bytecode": "0xbeef3", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01" + } + } + ], + "maxCumulativeGasUsed": 300000 + }`, expectedConfig: NetworkConfig{ - GenBlockNumber: 6934972, - PoEAddr: common.HexToAddress("0x2f612dc8fB986E7976AEfc13d8bB0Eb18488a4C9"), - MaticAddr: common.HexToAddress("0xEa2f9aC0cd926C92923355e88Af73Ee83F2D9C67"), - - GlobalExitRootManagerAddr: common.HexToAddress("0x9730d4ec6684E5567fB70B12d49Bf3f58f5ce4Cc"), - L2GlobalExitRootManagerAddr: common.HexToAddress("0xae4bb80be56b819606589de61d5ec3b522eeb032"), - SystemSCAddr: common.Address{}, - GlobalExitRootStoragePosition: 0, - LocalExitRootStoragePosition: 1, - OldStateRootPosition: 0, - L1ChainID: 5, + L2GlobalExitRootManagerAddr: common.HexToAddress("0xae4bb80be56b819606589de61d5ec3b522eeb032"), + L2BridgeAddr: common.HexToAddress("0x9d98deabc42dd696deb9e40b4f1cab7ddbf55988"), + L1Config: etherman.L1Config{ + L1ChainID: 420, + ZkEVMAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), + MaticAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), + GlobalExitRootManagerAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), + }, Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ + Root: common.HexToHash("0xBEEF"), + GenesisBlockNum: 69, + GenesisActions: []*state.GenesisAction{ { Address: "0xc949254d682d8c9ad5682521675b8f43b102aec4", Type: int(merkletree.LeafTypeNonce), @@ -152,15 +147,6 @@ func TestLoadCustomNetworkConfig(t *testing.T) { { description: "imported from network-config.example.json", inputConfigStr: `{ - "deploymentBlockNumber": 1, - "proofOfEfficiencyAddress": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", - "maticTokenAddress": "0x37AffAf737C3683aB73F6E1B0933b725Ab9796Aa", - "globalExitRootManagerAddress": "0x9730d4ec6684E5567fB70B12d49Bf3f58f5ce4Cc", - "systemSCAddr": "0x0000000000000000000000000000000000000000", - "globalExitRootStoragePosition": 2, - "localExitRootStoragePosition": 2, - "oldStateRootPosition": 0, - "l1ChainID": 1337, "genesis": [ { "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", @@ -178,18 +164,8 @@ func TestLoadCustomNetworkConfig(t *testing.T) { "maxCumulativeGasUsed": 123456 }`, expectedConfig: NetworkConfig{ - GenBlockNumber: 1, - PoEAddr: common.HexToAddress("0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"), - MaticAddr: common.HexToAddress("0x37AffAf737C3683aB73F6E1B0933b725Ab9796Aa"), - - GlobalExitRootManagerAddr: common.HexToAddress("0x9730d4ec6684E5567fB70B12d49Bf3f58f5ce4Cc"), - SystemSCAddr: common.Address{}, - GlobalExitRootStoragePosition: 2, - LocalExitRootStoragePosition: 2, - OldStateRootPosition: 0, - L1ChainID: 1337, Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", Type: int(merkletree.LeafTypeBalance), @@ -212,20 +188,18 @@ func TestLoadCustomNetworkConfig(t *testing.T) { { description: "not valid JSON gives error", inputConfigStr: "not a valid json", - expectedError: true, - expectedErrorMsg: "invalid character", + expectedErrorMsg: "failed to load genesis configuration from file. Error: invalid character 'o' in literal null (expecting 'u')", }, { description: "empty JSON gives error", - expectedError: true, - expectedErrorMsg: "unexpected end of JSON input", + expectedErrorMsg: "failed to load genesis configuration from file. Error: unexpected end of JSON input", }, } for _, tc := range tcs { tc := tc t.Run(tc.description, func(t *testing.T) { - file, err := ioutil.TempFile("", "loadCustomNetworkConfig") + file, err := os.CreateTemp("", "genesisConfig") require.NoError(t, err) defer func() { require.NoError(t, os.Remove(file.Name())) @@ -233,138 +207,21 @@ func TestLoadCustomNetworkConfig(t *testing.T) { require.NoError(t, os.WriteFile(file.Name(), []byte(tc.inputConfigStr), 0600)) flagSet := flag.NewFlagSet("test", flag.ExitOnError) - flagSet.String(FlagNetworkCfg, file.Name(), "") + flagSet.String(FlagNetwork, string(custom), "") + flagSet.String(FlagCustomNetwork, file.Name(), "") ctx := cli.NewContext(nil, flagSet, nil) - actualConfig, err := loadCustomNetworkConfig(ctx) - require.NoError(t, testutils.CheckError(err, tc.expectedError, tc.expectedErrorMsg)) - - require.Equal(t, tc.expectedConfig.GenBlockNumber, actualConfig.GenBlockNumber) - require.Equal(t, tc.expectedConfig.PoEAddr, actualConfig.PoEAddr) - require.Equal(t, tc.expectedConfig.MaticAddr, actualConfig.MaticAddr) - require.Equal(t, tc.expectedConfig.GlobalExitRootManagerAddr, actualConfig.GlobalExitRootManagerAddr) - require.Equal(t, tc.expectedConfig.L2GlobalExitRootManagerAddr, actualConfig.L2GlobalExitRootManagerAddr) - require.Equal(t, tc.expectedConfig.SystemSCAddr, actualConfig.SystemSCAddr) - require.Equal(t, tc.expectedConfig.GlobalExitRootStoragePosition, actualConfig.GlobalExitRootStoragePosition) - require.Equal(t, tc.expectedConfig.LocalExitRootStoragePosition, actualConfig.LocalExitRootStoragePosition) - require.Equal(t, tc.expectedConfig.OldStateRootPosition, actualConfig.OldStateRootPosition) - require.Equal(t, tc.expectedConfig.L1ChainID, actualConfig.L1ChainID) - - require.Equal(t, tc.expectedConfig.Genesis.Actions, actualConfig.Genesis.Actions) - }) - } -} - -func TestMergeNetworkConfig(t *testing.T) { - tcs := []struct { - description string - inputCustomConfig NetworkConfig - inputBaseConfig NetworkConfig - expectedOutputConfig NetworkConfig - }{ - { - description: "empty", - inputCustomConfig: NetworkConfig{}, - inputBaseConfig: NetworkConfig{}, - expectedOutputConfig: NetworkConfig{}, - }, - { - description: "matching keys", - inputCustomConfig: NetworkConfig{ - GenBlockNumber: 300, - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - MaticAddr: common.HexToAddress("0x1D217d81831009a5fE44C9a1Ee2480e48830CbD4"), - }, - inputBaseConfig: NetworkConfig{ - GenBlockNumber: 100, - PoEAddr: common.HexToAddress("0xb1Fe4a65D3392df68F96daC8eB4df56B2411afBf"), - MaticAddr: common.HexToAddress("0x6bad17aC92f0E9313E8c7c3B80E902f1c4D5255F"), - }, - expectedOutputConfig: NetworkConfig{ - GenBlockNumber: 300, - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - MaticAddr: common.HexToAddress("0x1D217d81831009a5fE44C9a1Ee2480e48830CbD4"), - }, - }, - { - description: "non-matching keys", - inputCustomConfig: NetworkConfig{ - GenBlockNumber: 300, - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - MaticAddr: common.HexToAddress("0x1D217d81831009a5fE44C9a1Ee2480e48830CbD4"), - }, - inputBaseConfig: NetworkConfig{ - PoEAddr: common.HexToAddress("0xb1Fe4a65D3392df68F96daC8eB4df56B2411afBf"), - L1ChainID: 5, - }, - expectedOutputConfig: NetworkConfig{ - L1ChainID: 5, - GenBlockNumber: 300, - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - MaticAddr: common.HexToAddress("0x1D217d81831009a5fE44C9a1Ee2480e48830CbD4"), - }, - }, - { - description: "nested keys", - inputCustomConfig: NetworkConfig{ - GenBlockNumber: 300, - Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - Type: int(merkletree.LeafTypeBalance), - Value: "1000000000000000000000", - }, - { - Address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - Type: int(merkletree.LeafTypeBalance), - Value: "2000000000000000000000", - }, - }, - }, - }, - inputBaseConfig: NetworkConfig{ - GenBlockNumber: 10, - }, - expectedOutputConfig: NetworkConfig{ - GenBlockNumber: 300, - Genesis: state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - Type: int(merkletree.LeafTypeBalance), - Value: "1000000000000000000000", - }, - { - Address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - Type: int(merkletree.LeafTypeBalance), - Value: "2000000000000000000000", - }, - }, - }, - }, - }, - { - description: "zero address doesn't overwrite destination", - inputCustomConfig: NetworkConfig{ - PoEAddr: common.Address{}, - }, - inputBaseConfig: NetworkConfig{ - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - }, - expectedOutputConfig: NetworkConfig{ - PoEAddr: common.HexToAddress("0xc949254d682d8c9ad5682521675b8f43b102aec4"), - }, - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - actualOutputConfig, err := mergeNetworkConfigs(tc.inputCustomConfig, tc.inputBaseConfig) - require.NoError(t, err) - - require.Equal(t, tc.expectedOutputConfig, actualOutputConfig) + c := &Config{} + if tc.expectedErrorMsg != "" { + panicFunc := func() { + c.loadNetworkConfig(ctx) + } + require.PanicsWithError(t, tc.expectedErrorMsg, panicFunc) + // require.Panics(t, panicFunc) + } else { + c.loadNetworkConfig(ctx) + require.Equal(t, tc.expectedConfig, c.NetworkConfig) + } }) } } diff --git a/config/prover.config.local.json b/config/prover.config.local.json deleted file mode 100644 index 2df29dbeb1..0000000000 --- a/config/prover.config.local.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "runProverServer": false, - "runProverServerMock": true, - "runProverClient": false, - - "runExecutorServer": true, - "runExecutorClient": false, - - "runStateDBServer": true, - "runStateDBTest": false, - - "runFile": false, - "runFileFast": false, - - "runKeccakScriptGenerator": false, - "runKeccakTest": false, - "runStorageSMTest": false, - "runBinarySMTest": false, - "runMemAlignSMTest": false, - "runStarkTest": false, - - "executeInParallel" : false, - "useMainExecGenerated" : false, - - "proverServerPort": 50051, - "proverServerMockPort": 50052, - "proverClientPort": 50051, - "proverServerMockTimeout": 60000000, - - "executorServerPort": 50071, - "executorClientPort": 50071, - "executorClientHost": "127.0.0.1", - - "stateDBServerPort": 50061, - "stateDBURL": "local", - - "inputFile": "input_executor.json", - "outputPath": "output", - "romFile": "rom.json", - "pilFile": "zkevm.pil.json", - "cmPolsFile": "commit.bin", - "constPolsFile": "constants.bin", - "constantsTreeFile": "constantstree.bin", - "scriptFile": "starkgen_bmscript.json", - "starkFile_disabled": "stark.json", - "verifierFile": "verifier.dat", - "witnessFile_disabled": "witness.wtns", - "starkVerifierFile": "starkverifier_0001.zkey", - "publicFile": "public.json", - "proofFile": "proof.json", - "keccakScriptFile": "keccak_script.json", - "keccakPolsFile_DISABLED": "keccak_pols.json", - "keccakConnectionsFile": "keccak_connections.json", - "storageRomFile": "storage_sm_rom.json", - "storagePilFile": "storage.pil.json", - "storagePolsFile": "storage.commit.bin", - "memoryPilFile": "mem.pil.json", - "memoryPolsFile": "mem.commit.bin", - "binaryPilFile": "binary.pil.json", - "binaryPolsFile": "binary.commit.bin", - "binaryConstPolsFile": "binary.constants.bin", - "starkInfoFile": "zkevm.starkinfo.json", - - "databaseURL": "postgresql://prover_user:prover_pass@zkevm-state-db:5432/prover_db", - "dbTableName": "state.merkletree", - "dbAsyncWrite": false, - "cleanerPollingPeriod": 600, - "requestsPersistence": 3600 -} diff --git a/config/readme.md b/config/readme.md index 92d2f6b66a..7137ad74b1 100644 --- a/config/readme.md +++ b/config/readme.md @@ -11,8 +11,6 @@ ZKEVM_NODE_DATABASE_PORT ZKEVM_NODE_ETHERMAN_URL ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH ZKEVM_NODE_ETHERMAN_PRIVATEKEYPASSWORD -ZKEVM_NODE_RPC_HOST -ZKEVM_NODE_RPC_PORT ZKEVM_NODE_SYNCHRONIZER_SYNCINTERVAL ZKEVM_NODE_SEQUENCER_INTERVALTOPROPOSEBATCH ZKEVM_NODE_SEQUENCER_SYNCEDBLOCKDIF diff --git a/config/testnetgenesis.go b/config/testnetgenesis.go new file mode 100644 index 0000000000..869850a10a --- /dev/null +++ b/config/testnetgenesis.go @@ -0,0 +1,108 @@ +package config + +// TestnetNetworkConfigJSON is the hardcoded network configuration to be used for the official mainnet setup +const TestnetNetworkConfigJSON = ` +{ + "l1Config" : { + "chainId": 5, + "polygonZkEVMAddress": "0xa997cfD539E703921fD1e3Cf25b4c241a27a4c7A", + "maticTokenAddress": "0x1319D23c2F7034F52Eb07399702B040bA278Ca49", + "polygonZkEVMGlobalExitRootAddress": "0x4d9427DCA0406358445bC0a8F88C26b704004f74" + }, + "root": "0x13a14c4a8288e782863d7ce916d224546c69dc428fbfa7115a0cc33a27a05b26", + "genesisBlockNumber": 8572998, + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0x39877a0c3cd148476DaA2475c77c478C62eC7509", + "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100e65780638da5cb5b146100fb578063e11ae6cb14610126578063f2fde38b1461013957600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610927565b610159565b005b6100886100983660046109c7565b6101cb565b3480156100a957600080fd5b506100bd6100b8366004610a1e565b61020d565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b50610088610220565b34801561010757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100bd565b610088610134366004610a40565b610234565b34801561014557600080fd5b50610088610154366004610a90565b61029b565b610161610357565b600061016e8585856103d8565b905061017a8183610537565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101d3610357565b6101de83838361057b565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b600061021983836105a9565b9392505050565b610228610357565b61023260006105b6565b565b61023c610357565b60006102498484846103d8565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b6102a3610357565b73ffffffffffffffffffffffffffffffffffffffff811661034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610354816105b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610342565b600083471015610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610342565b81516000036104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610342565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610342565b6060610219838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061062b565b60606105a1848484604051806060016040528060298152602001610b3d6029913961062b565b949350505050565b6000610219838330610744565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610342565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516106e69190610acf565b60006040518083038185875af1925050503d8060008114610723576040519150601f19603f3d011682016040523d82523d6000602084013e610728565b606091505b50915091506107398783838761076e565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156108045782516000036107fd5773ffffffffffffffffffffffffffffffffffffffff85163b6107fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610342565b50816105a1565b6105a183838151156108195781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103429190610aeb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261088d57600080fd5b813567ffffffffffffffff808211156108a8576108a861084d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108ee576108ee61084d565b8160405283815286602085880101111561090757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561093d57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561096357600080fd5b61096f8883890161087c565b9350606087013591508082111561098557600080fd5b506109928782880161087c565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff811681146109c257600080fd5b919050565b6000806000606084860312156109dc57600080fd5b6109e58461099e565b9250602084013567ffffffffffffffff811115610a0157600080fd5b610a0d8682870161087c565b925050604084013590509250925092565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600080600060608486031215610a5557600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a7a57600080fd5b610a868682870161087c565b9150509250925092565b600060208284031215610aa257600080fd5b6102198261099e565b60005b83811015610ac6578181015183820152602001610aae565b50506000910152565b60008251610ae1818460208701610aab565b9190910192915050565b6020815260008251806020840152610b0a816040850160208701610aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212200b8e3cd6bd762444a7eeff86e1cfcd7e1ce9524b715dcb70b2a4c2b70fd5188464736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000a0b02b28920812324f1cc3255bd8840867d3f227" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x40797c2f93298a44a893F43EdF1B33B63d7BA333", + "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b366004610608565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb36600461062c565b610269565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610694565b6102f7565b34801561014a57600080fd5b506100de61015936600461062c565b61038c565b34801561016a57600080fd5b506100de610179366004610608565b6103e8565b34801561018a57600080fd5b506100a0610199366004610608565b6104a4565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610788565b949350505050565b61025d6104f0565b6102676000610571565b565b6102716104f0565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156102db57600080fd5b505af11580156102ef573d6000803e3d6000fd5b505050505050565b6102ff6104f0565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061035590869086906004016107a5565b6000604051808303818588803b15801561036e57600080fd5b505af1158015610382573d6000803e3d6000fd5b5050505050505050565b6103946104f0565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102c1565b6103f06104f0565b73ffffffffffffffffffffffffffffffffffffffff8116610498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104a181610571565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161048f565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146104a157600080fd5b60006020828403121561061a57600080fd5b8135610625816105e6565b9392505050565b6000806040838503121561063f57600080fd5b823561064a816105e6565b9150602083013561065a816105e6565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156106a957600080fd5b83356106b4816105e6565b925060208401356106c4816105e6565b9150604084013567ffffffffffffffff808211156106e157600080fd5b818601915086601f8301126106f557600080fd5b81358181111561070757610707610665565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561074d5761074d610665565b8160405282815289602084870101111561076657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561079a57600080fd5b8151610625816105e6565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156107ef578581018301518582016060015282016107d3565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea2646970667358221220babd4ff1f5daee002b96cc86d8bb6c2c2c210ae3132df5ea384713352f7f15fe64736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000002245d7b6cb0b6870d1e28ac877ee355b9588869" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0x39e780D8800f7396e8B7530A8925B14025AedC77", + "bytecode": "0x6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000639578063ee25560b1462000651578063fb570834146200068257600080fd5b8063be5831c714620005ae578063cd58657914620005ea578063d02103ca146200060157600080fd5b80639e34070f11620000be5780639e34070f146200050a578063aaa13cc2146200054f578063bab161bf146200057457600080fd5b8063647c576c146200048657806379e2cf9714620004ab57806381b1c17414620004c357600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf2146200034b5780633ae05047146200037a5780633e197043146200039257600080fd5b80632d2c9d9414620002765780632dfdf0b5146200029b578063318aee3d14620002c257600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200023a5780632cffd02e146200025157600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed620006a7565b005b348015620001fc57600080fd5b50620002146200020e366004620032db565b62000705565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001cc565b620001ed6200024b36600462003372565b620007a8565b3480156200025e57600080fd5b50620001ed6200027036600462003409565b620009d0565b3480156200028357600080fd5b50620001ed6200029536600462003409565b62000f74565b348015620002a857600080fd5b50620002b360535481565b604051908152602001620001cc565b348015620002cf57600080fd5b5062000319620002e1366004620034ef565b606b6020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001cc565b3480156200035857600080fd5b50606c54620002149073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200038757600080fd5b50620002b362001178565b3480156200039f57600080fd5b50620002b3620003b136600462003526565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200049357600080fd5b50620001ed620004a5366004620035b0565b6200125e565b348015620004b857600080fd5b50620001ed620014ad565b348015620004d057600080fd5b5062000214620004e236600462003600565b606a6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200051757600080fd5b50620001c06200052936600462003600565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200055c57600080fd5b50620002146200056e3660046200361a565b620014e7565b3480156200058157600080fd5b506068546200059890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620005bb57600080fd5b506068546200059890790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001ed620005fb366004620036ce565b620016d3565b3480156200060e57600080fd5b50606854620002149065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200064657600080fd5b50620001ed62001c37565b3480156200065e57600080fd5b50620002b36200067036600462003600565b60696020526000908152604090205481565b3480156200068f57600080fd5b50620001c0620006a136600462003770565b62001c93565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006f9576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362001d7c565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091206000908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007e6576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8681166101009092041614806200080c5750600263ffffffff861610155b1562000844576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163388883488886053546040516200089a9998979695949392919062003806565b60405180910390a1620009b8620009b26001606860019054906101000a900463ffffffff16338989348989604051620008d592919062003881565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b62001e10565b8215620009c957620009c962001f27565b5050505050565b60685460ff161562000a0e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000a258b8b8b8b8b8b8b8b8b8b8b600062001ffc565b73ffffffffffffffffffffffffffffffffffffffff861662000b01576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a7a9190620038e6565b60006040518083038185875af1925050503d806000811462000ab9576040519150601f19603f3d011682016040523d82523d6000602084013e62000abe565b606091505b505090508062000afa576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000efc565b60685463ffffffff61010090910481169088160362000b435762000b3d73ffffffffffffffffffffffffffffffffffffffff87168585620021ed565b62000efc565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e6e576000808062000c1886880188620039fb565b92509250925060008584848460405162000c329062003292565b62000c409392919062003abd565b8190604051809103906000f590508015801562000c61573d6000803e3d6000fd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b15801562000cd757600080fd5b505af115801562000cec573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e5c95949392919062003afa565b60405180910390a15050505062000ef9565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000edf57600080fd5b505af115801562000ef4573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000fb2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000fc98b8b8b8b8b8b8b8b8b8b8b600162001ffc565b60008473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000ffc949392919062003b42565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200107f9190620038e6565b60006040518083038185875af1925050503d8060008114620010be576040519150601f19603f3d011682016040523d82523d6000602084013e620010c3565b606091505b5050905080620010ff576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562001255578083901c600116600103620011e65760338160208110620011b257620011b262003b8a565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062001213565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806200124c9062003be8565b91505062001183565b50919392505050565b600054610100900460ff16158080156200127f5750600054600160ff909116105b806200129b5750303b1580156200129b575060005460ff166001145b6200132d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200138c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905562001443620022c3565b8015620014a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff16101562000703576200070362001f27565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200157d9062003292565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620015c8908d908d908d908d908d9060200162003c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001606929160200162003c64565b604051602081830303815290604052805190602001206040516020016200168f94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff161562001711576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200171b62002366565b60685463ffffffff888116610100909204161480620017415750600263ffffffff881610155b1562001779576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060608773ffffffffffffffffffffffffffffffffffffffff8816620017df57883414620017d5576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001ad9565b341562001818576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901562001908576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac90604401600060405180830381600087803b158015620018db57600080fd5b505af1158015620018f0573d6000803e3d6000fd5b50505050806020015194508060000151935062001ad7565b85156200191d576200191d898b8989620023db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200198b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b1919062003c97565b9050620019d773ffffffffffffffffffffffffffffffffffffffff8b1633308e620028f9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801562001a45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6b919062003c97565b905062001a79828262003cb1565b6068548c9850610100900463ffffffff169650935062001a998762002959565b62001aa48c62002a71565b62001aaf8d62002b7e565b60405160200162001ac39392919062003abd565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e868860535460405162001b1b98979695949392919062003cc7565b60405180910390a162001c0f620009b2600085878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b861562001c205762001c2062001f27565b5050505062001c2e60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c89576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362002c80565b600084815b602081101562001d6e57600163ffffffff8616821c8116900362001d0a5785816020811062001ccb5762001ccb62003b8a565b60200201358260405160200162001cec929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001d59565b8186826020811062001d205762001d2062003b8a565b602002013560405160200162001d40929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d658162003be8565b91505062001c98565b50821490505b949350505050565b60685460ff161562001dba576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b80600162001e216020600262003e79565b62001e2d919062003cb1565b6053541062001e68576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060536000815462001e7b9062003be8565b9182905550905060005b602081101562001f17578082901c60011660010362001ebd57826033826020811062001eb55762001eb562003b8a565b015550505050565b6033816020811062001ed35762001ed362003b8a565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001f0e9062003be8565b91505062001e85565b5062001f2262003e87565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001fad62001178565b6040518263ffffffff1660e01b815260040162001fcc91815260200190565b600060405180830381600087803b15801562001fe757600080fd5b505af1158015620014a7573d6000803e3d6000fd5b6200200d8b63ffffffff1662002d10565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915260009165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303816000875af1158015620020b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020d6919062003c97565b90508060000362002112576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff88811661010090920416146200215c576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606854600090610100900463ffffffff166200217a5750896200217d565b508a5b620021a66200219d848c8c8c8c8c8c8c604051620008d592919062003881565b8f8f8462001c93565b620021dd576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001f229084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002d75565b600054610100900460ff166200235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6200070362002e88565b600260015403620023d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001324565b6002600155565b6000620023ec600482848662003eb6565b620023f79162003ee2565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620026765760008080808080806200245a896004818d62003eb6565b81019062002469919062003f2b565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614620024dd576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146200252d576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002567576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620026229190620038e6565b6000604051808303816000865af19150503d806000811462002661576040519150601f19603f3d011682016040523d82523d6000602084013e62002666565b606091505b50505050505050505050620009c9565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c0000000000000000000000000000000000000000000000000000000014620026f2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080808080806200270a8a6004818e62003eb6565b81019062002719919062003f86565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146200278f576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87163014620027df576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f1691620028a39190620038e6565b6000604051808303816000865af19150503d8060008114620028e2576040519150601f19603f3d011682016040523d82523d6000602084013e620028e7565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014a79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002240565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde03000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff861691620029dd9190620038e6565b600060405180830381855afa9150503d806000811462002a1a576040519150601f19603f3d011682016040523d82523d6000602084013e62002a1f565b606091505b50915091508162002a66576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d74565b62001d748162002f21565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b41000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff86169162002af59190620038e6565b600060405180830381855afa9150503d806000811462002b32576040519150601f19603f3d011682016040523d82523d6000602084013e62002b37565b606091505b50915091508162002a66576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d74565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169162002c019190620038e6565b600060405180830381855afa9150503d806000811462002c3e576040519150601f19603f3d011682016040523d82523d6000602084013e62002c43565b606091505b509150915081801562002c57575080516020145b62002c6457601262001d74565b8080602001905181019062001d74919062004012565b60018055565b60685460ff1662002cbd576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009c9576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031119092919063ffffffff16565b80519091501562001f22578080602001905181019062002dfa919062004032565b62001f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162001324565b600054610100900460ff1662002c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6060604082511062002f435781806020019051810190620007a2919062004052565b8151602003620030d35760005b60208110801562002f9b575082818151811062002f715762002f7162003b8a565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002fb6578062002fad8162003be8565b91505062002f50565b8060000362002ffa57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562003018576200301862003891565b6040519080825280601f01601f19166020018201604052801562003043576020820181803683370190505b50905060005b82811015620030cb5784818151811062003067576200306762003b8a565b602001015160f81c60f81b82828151811062003087576200308762003b8a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620030c28162003be8565b91505062003049565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d748484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051620031489190620038e6565b60006040518083038185875af1925050503d806000811462003187576040519150601f19603f3d011682016040523d82523d6000602084013e6200318c565b606091505b50915091506200319f87838387620031aa565b979650505050505050565b60608315620032455782516000036200323d5773ffffffffffffffffffffffffffffffffffffffff85163b6200323d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162001324565b508162001d74565b62001d7483838151156200325c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620013249190620040d2565b611b6680620040e883390190565b803563ffffffff811681146200310c57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620032d857600080fd5b50565b60008060408385031215620032ef57600080fd5b620032fa83620032a0565b915060208301356200330c81620032b5565b809150509250929050565b8015158114620032d857600080fd5b60008083601f8401126200333957600080fd5b50813567ffffffffffffffff8111156200335257600080fd5b6020830191508360208285010111156200336b57600080fd5b9250929050565b6000806000806000608086880312156200338b57600080fd5b6200339686620032a0565b94506020860135620033a881620032b5565b93506040860135620033ba8162003317565b9250606086013567ffffffffffffffff811115620033d757600080fd5b620033e58882890162003326565b969995985093965092949392505050565b806104008101831015620007a257600080fd5b60008060008060008060008060008060006105208c8e0312156200342c57600080fd5b620034388d8d620033f6565b9a50620034496104008d01620032a0565b99506104208c013598506104408c013597506200346a6104608d01620032a0565b96506104808c01356200347d81620032b5565b95506200348e6104a08d01620032a0565b94506104c08c0135620034a181620032b5565b93506104e08c013592506105008c013567ffffffffffffffff811115620034c757600080fd5b620034d58e828f0162003326565b915080935050809150509295989b509295989b9093969950565b6000602082840312156200350257600080fd5b81356200350f81620032b5565b9392505050565b60ff81168114620032d857600080fd5b600080600080600080600060e0888a0312156200354257600080fd5b87356200354f8162003516565b96506200355f60208901620032a0565b955060408801356200357181620032b5565b94506200358160608901620032a0565b935060808801356200359381620032b5565b9699959850939692959460a0840135945060c09093013592915050565b600080600060608486031215620035c657600080fd5b620035d184620032a0565b92506020840135620035e381620032b5565b91506040840135620035f581620032b5565b809150509250925092565b6000602082840312156200361357600080fd5b5035919050565b600080600080600080600060a0888a0312156200363657600080fd5b6200364188620032a0565b965060208801356200365381620032b5565b9550604088013567ffffffffffffffff808211156200367157600080fd5b6200367f8b838c0162003326565b909750955060608a01359150808211156200369957600080fd5b50620036a88a828b0162003326565b9094509250506080880135620036be8162003516565b8091505092959891949750929550565b600080600080600080600060c0888a031215620036ea57600080fd5b620036f588620032a0565b965060208801356200370781620032b5565b95506040880135945060608801356200372081620032b5565b93506080880135620037328162003317565b925060a088013567ffffffffffffffff8111156200374f57600080fd5b6200375d8a828b0162003326565b989b979a50959850939692959293505050565b60008060008061046085870312156200378857600080fd5b843593506200379b8660208701620033f6565b9250620037ac6104208601620032a0565b939692955092936104400135925050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620038678285018789620037bd565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811015620038dd578181015183820152602001620038c3565b50506000910152565b60008251620038fa818460208701620038c0565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200394e576200394e62003891565b604052919050565b600067ffffffffffffffff82111562003973576200397362003891565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620039b157600080fd5b8135620039c8620039c28262003956565b62003904565b818152846020838601011115620039de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562003a1157600080fd5b833567ffffffffffffffff8082111562003a2a57600080fd5b62003a38878388016200399f565b9450602086013591508082111562003a4f57600080fd5b5062003a5e868287016200399f565b9250506040840135620035f58162003516565b6000815180845262003a8b816020860160208601620038c0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062003ad2606083018662003a71565b828103602084015262003ae6818662003a71565b91505060ff83166040830152949350505050565b63ffffffff86168152600073ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200319f608083018486620037bd565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff8416602082015260606040820152600062003b80606083018486620037bd565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003c1c5762003c1c62003bb9565b5060010190565b60608152600062003c39606083018789620037bd565b828103602084015262003c4e818688620037bd565b91505060ff831660408301529695505050505050565b6000835162003c78818460208801620038c0565b83519083019062003c8e818360208801620038c0565b01949350505050565b60006020828403121562003caa57600080fd5b5051919050565b81810381811115620007a257620007a262003bb9565b600061010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003d278285018762003a71565b925080851660e085015250509998505050505050505050565b600181815b8085111562003d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d835762003d8362003bb9565b8085161562003d9157918102915b93841c939080029062003d45565b509250929050565b60008262003db857506001620007a2565b8162003dc757506000620007a2565b816001811462003de0576002811462003deb5762003e0b565b6001915050620007a2565b60ff84111562003dff5762003dff62003bb9565b50506001821b620007a2565b5060208310610133831016604e8410600b841016171562003e30575081810a620007a2565b62003e3c838362003d40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003e715762003e7162003bb9565b029392505050565b60006200350f838362003da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000808585111562003ec757600080fd5b8386111562003ed557600080fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003f235780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a03121562003f4757600080fd5b873562003f5481620032b5565b9650602088013562003f6681620032b5565b955060408801359450606088013593506080880135620035938162003516565b600080600080600080600080610100898b03121562003fa457600080fd5b883562003fb181620032b5565b9750602089013562003fc381620032b5565b96506040890135955060608901359450608089013562003fe38162003317565b935060a089013562003ff58162003516565b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156200402557600080fd5b81516200350f8162003516565b6000602082840312156200404557600080fd5b81516200350f8162003317565b6000602082840312156200406557600080fd5b815167ffffffffffffffff8111156200407d57600080fd5b8201601f810184136200408f57600080fd5b8051620040a0620039c28262003956565b818152856020838501011115620040b657600080fd5b620040c9826020830160208601620038c0565b95945050505050565b6020815260006200350f602083018462003a7156fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220addfd62f466d34ee002afbb4ae37b6be56ad421fe773f800badeb4ce1025089864736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "200000000000000000000000000", + "nonce": "1", + "address": "0xF6BEEeBB578e214CA9E23B0e9683454Ff88Ed2A7", + "bytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461088b565b610135565b61006b6100a33660046108a6565b61017f565b3480156100b457600080fd5b506100bd6101f3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461088b565b610231565b34801561011257600080fd5b506100bd61025e565b6101236102d4565b61013361012e6103ab565b6103b5565b565b61013d6103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481604051806020016040528060008152506000610419565b50565b61017461011b565b6101876103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101eb576101e68383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610419915050565b505050565b6101e661011b565b60006101fd6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103ab565b905090565b61022e61011b565b90565b6102396103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481610444565b60006102686103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103d9565b60606102b183836040518060600160405280602781526020016109bb602791396104a5565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6102dc6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061022161052a565b3660008037600080366000845af43d6000803e8080156103d4573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b61042283610552565b60008251118061042f5750805b156101e65761043e838361028c565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61046d6103d9565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16101748161059f565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516104cf919061094d565b600060405180830381855af49150503d806000811461050a576040519150601f19603f3d011682016040523d82523d6000602084013e61050f565b606091505b5091509150610520868383876106ab565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103fd565b61055b81610753565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a2565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6060831561074157825160000361073a5773ffffffffffffffffffffffffffffffffffffffff85163b61073a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a2565b508161074b565b61074b838361081e565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81163b6107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016103a2565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610665565b81511561082e5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a29190610969565b803573ffffffffffffffffffffffffffffffffffffffff8116811461088657600080fd5b919050565b60006020828403121561089d57600080fd5b6102b182610862565b6000806000604084860312156108bb57600080fd5b6108c484610862565b9250602084013567ffffffffffffffff808211156108e157600080fd5b818601915086601f8301126108f557600080fd5b81358181111561090457600080fd5b87602082850101111561091657600080fd5b6020830194508093505050509250925092565b60005b8381101561094457818101518382015260200161092c565b50506000910152565b6000825161095f818460208701610929565b9190910192915050565b6020815260008251806020840152610988816040850160208701610929565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a1af0d6cb4f1e31496a4c5c1448913bce4bd6ad3a39e47c6f7190c114d6f9bf464736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000068": "0x00000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa0000000100", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x00000000000000000000000040797c2f93298a44a893f43edf1b33b63d7ba333", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000039e780d8800f7396e8b7530a8925b14025aedc77" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x77Fc57b154fCF8320Df2C2e6C044AA50141c023b", + "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610162565b60006020819052908152604090205481565b6100a061009b366004610162565b6100ee565b005b6100c97f000000000000000000000000f6beeebb578e214ca9e23b0e9683454ff88ed2a781565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f6beeebb578e214ca9e23b0e9683454ff88ed2a7161461015d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b60006020828403121561017457600080fd5b503591905056fea2646970667358221220a187fc278346c1b61c449ea3641002b6eac2bda3351a122a12c35099f933696864736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106ca565b610118565b61005b6100933660046106e5565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106ca565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103f1565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107e460279139610445565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb610519565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b83610541565b6040516001600160a01b038416907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000825111806103dc5750805b156101c3576103eb8383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a61035f565b604080516001600160a01b03928316815291841660208301520160405180910390a1610154816105e9565b6060833b6104a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b0316856040516104bf9190610794565b600060405180830381855af49150503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b509150915061050f828286610675565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b803b6105a55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b03811661064e5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036105c8565b60608315610684575081610285565b8251156106945782518084602001fd5b8160405162461bcd60e51b815260040161032891906107b0565b80356001600160a01b03811681146106c557600080fd5b919050565b6000602082840312156106dc57600080fd5b610285826106ae565b6000806000604084860312156106fa57600080fd5b610703846106ae565b9250602084013567ffffffffffffffff8082111561072057600080fd5b818601915086601f83011261073457600080fd5b81358181111561074357600080fd5b87602082850101111561075557600080fd5b6020830194508093505050509250925092565b60005b8381101561078357818101518382015260200161076b565b838111156103eb5750506000910152565b600082516107a6818460208701610768565b9190910192915050565b60208152600082518060208401526107cf816040850160208701610768565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204675187caf3a43285d9a2c1844a981e977bd52a85ff073e7fc649f73847d70a464736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x00000000000000000000000040797c2f93298a44a893f43edf1b33b63d7ba333", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000077fc57b154fcf8320df2c2e6c044aa50141c023b" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0x02245d7B6CB0b6870d1e28AC877EE355b9588869", + "bytecode": "0x6080604052600436106101c65760003560e01c806364d62353116100f7578063b1c5f42711610095578063d547741f11610064578063d547741f14610661578063e38335e514610681578063f23a6e6114610694578063f27a0c92146106d957600080fd5b8063b1c5f427146105af578063bc197c81146105cf578063c4d252f514610614578063d45c44351461063457600080fd5b80638f61f4f5116100d15780638f61f4f5146104e157806391d1485414610515578063a217fddf14610566578063b08e51c01461057b57600080fd5b806364d62353146104815780638065657f146104a15780638f2a0bb0146104c157600080fd5b8063248a9ca31161016457806331d507501161013e57806331d50750146103c857806336568abe146103e85780633a6aae7214610408578063584b153e1461046157600080fd5b8063248a9ca3146103475780632ab0f529146103775780632f2ff15d146103a857600080fd5b80630d3cf6fc116101a05780630d3cf6fc1461026b578063134008d31461029f57806313bc9f20146102b2578063150b7a02146102d257600080fd5b806301d5062a146101d257806301ffc9a7146101f457806307bd02651461022957600080fd5b366101cd57005b600080fd5b3480156101de57600080fd5b506101f26101ed366004611c12565b6106ee565b005b34801561020057600080fd5b5061021461020f366004611c87565b610783565b60405190151581526020015b60405180910390f35b34801561023557600080fd5b5061025d7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610220565b34801561027757600080fd5b5061025d7f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101f26102ad366004611cc9565b6107df565b3480156102be57600080fd5b506102146102cd366004611d35565b6108d7565b3480156102de57600080fd5b506103166102ed366004611e5a565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610220565b34801561035357600080fd5b5061025d610362366004611d35565b60009081526020819052604090206001015490565b34801561038357600080fd5b50610214610392366004611d35565b6000908152600160208190526040909120541490565b3480156103b457600080fd5b506101f26103c3366004611ec2565b6108fd565b3480156103d457600080fd5b506102146103e3366004611d35565b610927565b3480156103f457600080fd5b506101f2610403366004611ec2565b610940565b34801561041457600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610220565b34801561046d57600080fd5b5061021461047c366004611d35565b6109f8565b34801561048d57600080fd5b506101f261049c366004611d35565b610a0e565b3480156104ad57600080fd5b5061025d6104bc366004611cc9565b610ade565b3480156104cd57600080fd5b506101f26104dc366004611f33565b610b1d565b3480156104ed57600080fd5b5061025d7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561052157600080fd5b50610214610530366004611ec2565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561057257600080fd5b5061025d600081565b34801561058757600080fd5b5061025d7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156105bb57600080fd5b5061025d6105ca366004611fe5565b610d4f565b3480156105db57600080fd5b506103166105ea36600461210e565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b34801561062057600080fd5b506101f261062f366004611d35565b610d94565b34801561064057600080fd5b5061025d61064f366004611d35565b60009081526001602052604090205490565b34801561066d57600080fd5b506101f261067c366004611ec2565b610e8f565b6101f261068f366004611fe5565b610eb4565b3480156106a057600080fd5b506103166106af3660046121b8565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106e557600080fd5b5061025d611161565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161071881611204565b6000610728898989898989610ade565b90506107348184611211565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161077096959493929190612266565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107d957506107d98261135e565b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661085c5761085c81336113f5565b600061086c888888888888610ade565b905061087881856114ad565b610884888888886115ea565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516108bc94939291906122b1565b60405180910390a36108cd816116ee565b5050505050505050565b6000818152600160205260408120546001811180156108f65750428111155b9392505050565b60008281526020819052604090206001015461091881611204565b6109228383611797565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109f48282611887565b5050565b6000818152600160208190526040822054610939565b333014610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109e1565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610afb96959493929190612266565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b4781611204565b888714610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b888514610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b6000610c778b8b8b8b8b8b8b8b610d4f565b9050610c838184611211565b60005b8a811015610d415780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610cc357610cc36122f1565b9050602002016020810190610cd89190612320565b8d8d86818110610cea57610cea6122f1565b905060200201358c8c87818110610d0357610d036122f1565b9050602002810190610d15919061233b565b8c8b604051610d2996959493929190612266565b60405180910390a3610d3a816123cf565b9050610c86565b505050505050505050505050565b60008888888888888888604051602001610d709897969594939291906124b7565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610dbe81611204565b610dc7826109f8565b610e53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109e1565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610eaa81611204565b6109228383611887565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610f3157610f3181336113f5565b878614610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b87841461104f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b60006110618a8a8a8a8a8a8a8a610d4f565b905061106d81856114ad565b60005b8981101561114b5760008b8b8381811061108c5761108c6122f1565b90506020020160208101906110a19190612320565b905060008a8a848181106110b7576110b76122f1565b9050602002013590503660008a8a868181106110d5576110d56122f1565b90506020028101906110e7919061233b565b915091506110f7848484846115ea565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161112e94939291906122b1565b60405180910390a35050505080611144906123cf565b9050611070565b50611155816116ee565b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f2919061257e565b156111fd5750600090565b5060025490565b61120e81336113f5565b50565b61121a82610927565b156112a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109e1565b6112af611161565b81101561133e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109e1565b61134881426125a0565b6000928352600160205260409092209190915550565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107d957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107d9565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f4576114338161193e565b61143e83602061195d565b60405160200161144f9291906125d7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109e191600401612658565b6114b6826108d7565b611542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b80158061155e5750600081815260016020819052604090912054145b6109f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109e1565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516116149291906126a9565b60006040518083038185875af1925050503d8060008114611651576040519150601f19603f3d011682016040523d82523d6000602084013e611656565b606091505b50509050806116e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109e1565b5050505050565b6116f7816108d7565b611783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556118293390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107d973ffffffffffffffffffffffffffffffffffffffff831660145b6060600061196c8360026126b9565b6119779060026125a0565b67ffffffffffffffff81111561198f5761198f611d4e565b6040519080825280601f01601f1916602001820160405280156119b9576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106119f0576119f06122f1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a5357611a536122f1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000611a8f8460026126b9565b611a9a9060016125a0565b90505b6001811115611b37577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611adb57611adb6122f1565b1a60f81b828281518110611af157611af16122f1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93611b30816126d0565b9050611a9d565b5083156108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109e1565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bc457600080fd5b919050565b60008083601f840112611bdb57600080fd5b50813567ffffffffffffffff811115611bf357600080fd5b602083019150836020828501011115611c0b57600080fd5b9250929050565b600080600080600080600060c0888a031215611c2d57600080fd5b611c3688611ba0565b965060208801359550604088013567ffffffffffffffff811115611c5957600080fd5b611c658a828b01611bc9565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611c9957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108f657600080fd5b60008060008060008060a08789031215611ce257600080fd5b611ceb87611ba0565b955060208701359450604087013567ffffffffffffffff811115611d0e57600080fd5b611d1a89828a01611bc9565b979a9699509760608101359660809091013595509350505050565b600060208284031215611d4757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611dc457611dc4611d4e565b604052919050565b600082601f830112611ddd57600080fd5b813567ffffffffffffffff811115611df757611df7611d4e565b611e2860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d7d565b818152846020838601011115611e3d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611e7057600080fd5b611e7985611ba0565b9350611e8760208601611ba0565b925060408501359150606085013567ffffffffffffffff811115611eaa57600080fd5b611eb687828801611dcc565b91505092959194509250565b60008060408385031215611ed557600080fd5b82359150611ee560208401611ba0565b90509250929050565b60008083601f840112611f0057600080fd5b50813567ffffffffffffffff811115611f1857600080fd5b6020830191508360208260051b8501011115611c0b57600080fd5b600080600080600080600080600060c08a8c031215611f5157600080fd5b893567ffffffffffffffff80821115611f6957600080fd5b611f758d838e01611eee565b909b50995060208c0135915080821115611f8e57600080fd5b611f9a8d838e01611eee565b909950975060408c0135915080821115611fb357600080fd5b50611fc08c828d01611eee565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b03121561200157600080fd5b883567ffffffffffffffff8082111561201957600080fd5b6120258c838d01611eee565b909a50985060208b013591508082111561203e57600080fd5b61204a8c838d01611eee565b909850965060408b013591508082111561206357600080fd5b506120708b828c01611eee565b999c989b509699959896976060870135966080013595509350505050565b600082601f83011261209f57600080fd5b8135602067ffffffffffffffff8211156120bb576120bb611d4e565b8160051b6120ca828201611d7d565b92835284810182019282810190878511156120e457600080fd5b83870192505b84831015612103578235825291830191908301906120ea565b979650505050505050565b600080600080600060a0868803121561212657600080fd5b61212f86611ba0565b945061213d60208701611ba0565b9350604086013567ffffffffffffffff8082111561215a57600080fd5b61216689838a0161208e565b9450606088013591508082111561217c57600080fd5b61218889838a0161208e565b9350608088013591508082111561219e57600080fd5b506121ab88828901611dcc565b9150509295509295909350565b600080600080600060a086880312156121d057600080fd5b6121d986611ba0565b94506121e760208701611ba0565b93506040860135925060608601359150608086013567ffffffffffffffff81111561221157600080fd5b6121ab88828901611dcc565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a06040820152600061229c60a08301868861221d565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006122e760608301848661221d565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561233257600080fd5b6108f682611ba0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261237057600080fd5b83018035915067ffffffffffffffff82111561238b57600080fd5b602001915036819003821315611c0b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612400576124006123a0565b5060010190565b81835260006020808501808196508560051b810191508460005b878110156124aa57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301811261246057600080fd5b8701858101903567ffffffffffffffff81111561247c57600080fd5b80360382131561248b57600080fd5b61249686828461221d565b9a87019a9550505090840190600101612421565b5091979650505050505050565b60a0808252810188905260008960c08301825b8b8110156125055773ffffffffffffffffffffffffffffffffffffffff6124f084611ba0565b168252602092830192909101906001016124ca565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89111561253e57600080fd5b8860051b9150818a602083013701828103602090810160408501526125669082018789612407565b60608401959095525050608001529695505050505050565b60006020828403121561259057600080fd5b815180151581146108f657600080fd5b808201808211156107d9576107d96123a0565b60005b838110156125ce5781810151838201526020016125b6565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161260f8160178501602088016125b3565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161264c8160288401602088016125b3565b01602801949350505050565b60208152600082518060208401526126778160408501602087016125b3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b8183823760009101908152919050565b80820281158282048414176107d9576107d96123a0565b6000816126df576126df6123a0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220288c3dd40a2ba96edf066502722584177809ebdb47c0cf9ee8df6f07954c373064736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000015180", + "0xbdd73c6ebfb442c137537be0985acf11af8e6133078bc51ef9094071cb0ca475": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x92b79801e6a3d148a516c908cc0bbad93771fa74468b7757a14aa55532d092de": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x43e090632490f7d46c400129311fff008a7688bb3d4aebdf80607456b452cf04": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x5af21cf0316499c6925cf9be0331b8bd150a1fa4c19d24a043b45f0cf15357c3": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0xaf021eeb38644155cd697b3ce0ec4fdac818d29c448a9f9d9bafc293723c6cd8": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0xB83a574B3966F7dc1d38d162FA154F2A57D608Bb" + }, + { + "accountName": "deployer", + "balance": "0", + "nonce": "8", + "address": "0xA0B02B28920812324f1cC3255bd8840867d3f227" + } + ] + } + +` diff --git a/config/types/duration_test.go b/config/types/duration_test.go new file mode 100644 index 0000000000..71e06a04ba --- /dev/null +++ b/config/types/duration_test.go @@ -0,0 +1,54 @@ +package types + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDurationUnmarshal(t *testing.T) { + type testCase struct { + name string + input string + expectedResult *Duration + expectedErr error + } + + testCases := []testCase{ + { + name: "valid duration", + input: "60s", + expectedResult: &Duration{Duration: time.Minute}, + }, + { + name: "int value", + input: "60", + expectedErr: fmt.Errorf("time: missing unit in duration \"60\""), + }, + { + name: "no duration value", + input: "abc", + expectedErr: fmt.Errorf("time: invalid duration \"abc\""), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + var d Duration + input, err := json.Marshal(testCase.input) + require.NoError(t, err) + err = json.Unmarshal(input, &d) + + if testCase.expectedResult != nil { + require.Equal(t, (*testCase.expectedResult).Nanoseconds(), d.Nanoseconds()) + } + + if err != nil { + require.Equal(t, testCase.expectedErr.Error(), err.Error()) + } + }) + } +} diff --git a/config/types/keystore.go b/config/types/keystore.go new file mode 100644 index 0000000000..620834e9da --- /dev/null +++ b/config/types/keystore.go @@ -0,0 +1,10 @@ +package types + +// KeystoreFileConfig has all the information needed to load a private key from a key store file +type KeystoreFileConfig struct { + // Path is the file path for the key store file + Path string `mapstructure:"Path"` + + // Password is the password to decrypt the key store file + Password string `mapstructure:"Password"` +} diff --git a/db/db.go b/db/db.go index d2c9a1352f..1b1e1d3f7a 100644 --- a/db/db.go +++ b/db/db.go @@ -17,14 +17,11 @@ const ( StateMigrationName = "zkevm-state-db" // PoolMigrationName is the name of the migration used by packr to pack the migration file PoolMigrationName = "zkevm-pool-db" - // RPCMigrationName is the name of the migration used by packr to pack the migration file - RPCMigrationName = "zkevm-rpc-db" ) var packrMigrations = map[string]*packr.Box{ StateMigrationName: packr.New(StateMigrationName, "./migrations/state"), PoolMigrationName: packr.New(PoolMigrationName, "./migrations/pool"), - RPCMigrationName: packr.New(RPCMigrationName, "./migrations/rpc"), } // NewSQLDB creates a new SQL DB @@ -47,11 +44,18 @@ func NewSQLDB(cfg Config) (*pgxpool.Pool, error) { // RunMigrationsUp runs migrate-up for the given config. func RunMigrationsUp(cfg Config, name string) error { + log.Info("running migrations up") return runMigrations(cfg, name, migrate.Up) } +// CheckMigrations runs migrate-up for the given config. +func CheckMigrations(cfg Config, name string) error { + return checkMigrations(cfg, name, migrate.Up) +} + // RunMigrationsDown runs migrate-down for the given config. func RunMigrationsDown(cfg Config, name string) error { + log.Info("running migrations down") return runMigrations(cfg, name, migrate.Down) } @@ -79,3 +83,44 @@ func runMigrations(cfg Config, packrName string, direction migrate.MigrationDire log.Info("successfully ran ", nMigrations, " migrations") return nil } + +func checkMigrations(cfg Config, packrName string, direction migrate.MigrationDirection) error { + c, err := pgx.ParseConfig(fmt.Sprintf("postgres://%s:%s@%s:%s/%s", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name)) + if err != nil { + return err + } + db := stdlib.OpenDB(*c) + + box, ok := packrMigrations[packrName] + if !ok { + return fmt.Errorf("packr box not found with name: %v", packrName) + } + + migrationSource := &migrate.PackrMigrationSource{Box: box} + migrations, err := migrationSource.FindMigrations() + if err != nil { + log.Errorf("error getting migrations from source: %v", err) + return err + } + + var expected int + for _, migration := range migrations { + if len(migration.Up) != 0 { + expected++ + } + } + + var actual int + query := `SELECT COUNT(1) FROM public.gorp_migrations` + err = db.QueryRow(query).Scan(&actual) + if err != nil { + log.Error("error getting migrations count: ", err) + return err + } + if expected == actual { + log.Infof("Found %d migrations as expected", actual) + } else { + return fmt.Errorf("error the component needs to run %d migrations before starting. DB only contains %d migrations", expected, actual) + } + return nil +} diff --git a/db/migrations/pool/0001.sql b/db/migrations/pool/0001.sql index e44b9bfcc0..f88321daed 100644 --- a/db/migrations/pool/0001.sql +++ b/db/migrations/pool/0001.sql @@ -4,7 +4,7 @@ DROP SCHEMA IF EXISTS pool CASCADE; -- +migrate Up CREATE SCHEMA pool; -CREATE TABLE pool.txs +CREATE TABLE pool.transaction ( hash VARCHAR PRIMARY KEY, encoded VARCHAR, @@ -21,11 +21,13 @@ CREATE TABLE pool.txs used_arithmetics INTEGER, used_binaries INTEGER, used_steps INTEGER, + failed_counter DECIMAL(78, 0) DEFAULT 0, received_at TIMESTAMP WITH TIME ZONE NOT NULL, from_address varchar NOT NULL ); -CREATE INDEX idx_state_gas_price_nonce ON pool.txs (status, gas_price, nonce); +CREATE INDEX idx_state_gas_price_nonce ON pool.transaction (status, gas_price, nonce); +CREATE INDEX idx_failed_counter ON pool.transaction (failed_counter); CREATE TABLE pool.gas_price ( diff --git a/db/migrations/pool/0002.sql b/db/migrations/pool/0002.sql index e2f9865218..db342f7d79 100644 --- a/db/migrations/pool/0002.sql +++ b/db/migrations/pool/0002.sql @@ -1,7 +1,7 @@ -- +migrate Up -ALTER TABLE pool.txs ADD COLUMN failed_counter DECIMAL(78, 0) DEFAULT 0; -CREATE INDEX idx_failed_counter ON pool.txs (failed_counter); +ALTER TABLE pool.transaction +ADD COLUMN is_wip BOOLEAN; -- +migrate Down -DROP INDEX pool.idx_failed_counter; -ALTER TABLE pool.txs DROP COLUMN failed_counter; +ALTER TABLE pool.transaction +DROP COLUMN is_wip; diff --git a/db/migrations/pool/0003.sql b/db/migrations/pool/0003.sql new file mode 100644 index 0000000000..d683825c8a --- /dev/null +++ b/db/migrations/pool/0003.sql @@ -0,0 +1,13 @@ +-- +migrate Up +ALTER TABLE pool.transaction +DROP COLUMN failed_counter; + +ALTER TABLE pool.transaction +ADD COLUMN ip VARCHAR; + +-- +migrate Down +ALTER TABLE pool.transaction +ADD COLUMN failed_counter DECIMAL(78, 0) DEFAULT 0; + +ALTER TABLE pool.transaction +DROP COLUMN ip; diff --git a/db/migrations/pool/0004.sql b/db/migrations/pool/0004.sql new file mode 100644 index 0000000000..021aa0b796 --- /dev/null +++ b/db/migrations/pool/0004.sql @@ -0,0 +1,5 @@ +-- +migrate Up +-- Nothing to do here fix in 0005.sql + +-- +migrate Down +-- Nothing to do here fix in 0005.sql diff --git a/db/migrations/pool/0005.sql b/db/migrations/pool/0005.sql new file mode 100644 index 0000000000..1c6ec09f5b --- /dev/null +++ b/db/migrations/pool/0005.sql @@ -0,0 +1,13 @@ +-- +migrate Up +UPDATE pool.transaction +SET ip = '' WHERE ip IS NULL; +ALTER TABLE pool.transaction +ALTER COLUMN ip SET NOT NULL; +ALTER TABLE pool.transaction +ALTER COLUMN ip SET DEFAULT ''; + +-- +migrate Down +ALTER TABLE pool.transaction +ALTER COLUMN ip DROP NOT NULL; +ALTER TABLE pool.transaction +ALTER COLUMN ip DROP DEFAULT; diff --git a/db/migrations/pool/0006.sql b/db/migrations/pool/0006.sql new file mode 100644 index 0000000000..561252ca3a --- /dev/null +++ b/db/migrations/pool/0006.sql @@ -0,0 +1,7 @@ +-- +migrate Up +ALTER TABLE pool.transaction +ADD COLUMN deposit_count BIGINT; + +-- +migrate Down +ALTER TABLE pool.transaction +DROP COLUMN deposit_count; diff --git a/db/migrations/pool/0007.sql b/db/migrations/pool/0007.sql new file mode 100644 index 0000000000..20349062b7 --- /dev/null +++ b/db/migrations/pool/0007.sql @@ -0,0 +1,8 @@ +-- +migrate Up +CREATE TABLE pool.blocked +( + addr varchar NOT NULL PRIMARY KEY +); + +-- +migrate Down +DROP TABLE pool.blocked; diff --git a/db/migrations/pool/0008.sql b/db/migrations/pool/0008.sql new file mode 100644 index 0000000000..f2ad4f4fe2 --- /dev/null +++ b/db/migrations/pool/0008.sql @@ -0,0 +1,5 @@ +-- +migrate Up +ALTER TABLE pool.transaction ADD COLUMN failed_reason VARCHAR; + +-- +migrate Down +ALTER TABLE pool.transaction DROP COLUMN failed_reason; diff --git a/db/migrations/rpc/0001.sql b/db/migrations/rpc/0001.sql deleted file mode 100644 index d8415d2541..0000000000 --- a/db/migrations/rpc/0001.sql +++ /dev/null @@ -1,13 +0,0 @@ --- +migrate Down -DROP SCHEMA IF EXISTS rpc CASCADE; - --- +migrate Up -CREATE SCHEMA rpc; - -CREATE TABLE rpc.filters -( - id SERIAL PRIMARY KEY, - filter_type VARCHAR(15) NOT NULL, - parameters JSONB NOT NULL, - last_poll TIMESTAMP NOT NULL -); diff --git a/db/migrations/state/0001.sql b/db/migrations/state/0001.sql index 3a6ff463b7..f09e06d343 100644 --- a/db/migrations/state/0001.sql +++ b/db/migrations/state/0001.sql @@ -12,15 +12,27 @@ CREATE TABLE state.block received_at TIMESTAMP WITH TIME ZONE NOT NULL ); +CREATE TABLE state.forced_batch +( + forced_batch_num BIGINT PRIMARY KEY, + global_exit_root VARCHAR, + timestamp TIMESTAMP WITH TIME ZONE NOT NULL, + raw_txs_data VARCHAR, + coinbase VARCHAR, + block_num BIGINT NOT NULL REFERENCES state.block (block_num) ON DELETE CASCADE +); + CREATE TABLE state.batch ( --batch abstraction: will be created through trusted state batch_num BIGINT PRIMARY KEY, global_exit_root VARCHAR, local_exit_root VARCHAR, state_root VARCHAR, - timestamp TIMESTAMP, + acc_input_hash VARCHAR, + timestamp TIMESTAMP WITH TIME ZONE, coinbase VARCHAR, - raw_txs_data BYTEA + raw_txs_data BYTEA, + forced_batch_num BIGINT REFERENCES state.forced_batch(forced_batch_num) ); CREATE TABLE state.virtual_batch @@ -36,18 +48,9 @@ CREATE TABLE state.verified_batch batch_num BIGINT PRIMARY KEY REFERENCES state.virtual_batch (batch_num) ON DELETE CASCADE, tx_hash VARCHAR, aggregator VARCHAR, - block_num BIGINT NOT NULL REFERENCES state.block (block_num) ON DELETE CASCADE -); - -CREATE TABLE state.forced_batch -( - forced_batch_num BIGINT PRIMARY KEY, - global_exit_root VARCHAR, - timestamp TIMESTAMP, - raw_txs_data VARCHAR, - coinbase VARCHAR, - batch_num BIGINT, -- It can be null if the batch state is not trusted - block_num BIGINT NOT NULL REFERENCES state.block (block_num) ON DELETE CASCADE + state_root VARCHAR, + block_num BIGINT NOT NULL REFERENCES state.block (block_num) ON DELETE CASCADE, + is_trusted BOOLEAN DEFAULT true ); CREATE TABLE state.l2block @@ -59,6 +62,7 @@ CREATE TABLE state.l2block parent_hash VARCHAR, state_root VARCHAR, received_at TIMESTAMP WITH TIME ZONE NOT NULL, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, batch_num BIGINT NOT NULL REFERENCES state.batch (batch_num) ON DELETE CASCADE ); @@ -72,8 +76,9 @@ CREATE TABLE state.transaction CREATE TABLE state.exit_root ( + id SERIAL PRIMARY KEY, block_num BIGINT NOT NULL REFERENCES state.block (block_num) ON DELETE CASCADE, - global_exit_root_num BIGINT PRIMARY KEY, + timestamp TIMESTAMP WITH TIME ZONE NOT NULL, mainnet_exit_root BYTEA, rollup_exit_root BYTEA, global_exit_root BYTEA @@ -118,6 +123,44 @@ CREATE TABLE state.log CREATE TABLE state.proof ( - batch_num BIGINT NOT NULL PRIMARY KEY REFERENCES state.batch (batch_num) ON DELETE CASCADE, - proof jsonb + batch_num BIGINT NOT NULL REFERENCES state.batch (batch_num) ON DELETE CASCADE, + batch_num_final BIGINT NOT NULL REFERENCES state.batch (batch_num) ON DELETE CASCADE, + proof VARCHAR, + proof_id VARCHAR, + input_prover VARCHAR, + prover VARCHAR, + generating BOOLEAN DEFAULT FALSE, + PRIMARY KEY (batch_num, batch_num_final) +); + +CREATE TABLE IF NOT EXISTS state.sequences +( --Allowed Verifications + from_batch_num BIGINT REFERENCES state.batch (batch_num) ON DELETE CASCADE, + to_batch_num BIGINT REFERENCES state.batch (batch_num) ON DELETE CASCADE +); + +CREATE TABLE state.monitored_txs +( + owner VARCHAR NOT NULL, + id VARCHAR NOT NULL, + from_addr VARCHAR NOT NULL, + to_addr VARCHAR, + nonce DECIMAL(78, 0) NOT NULL, + value DECIMAL(78, 0), + data VARCHAR, + gas DECIMAL(78, 0) NOT NULL, + gas_price DECIMAL(78, 0) NOT NULL, + status VARCHAR NOT NULL, + history VARCHAR[], + block_num BIGINT, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, + updated_at TIMESTAMP WITH TIME ZONE NOT NULL, + PRIMARY KEY (owner, id) ); + +CREATE TABLE state.debug +( + error_type VARCHAR, + timestamp timestamp, + payload VARCHAR +); \ No newline at end of file diff --git a/db/migrations/state/0002.sql b/db/migrations/state/0002.sql new file mode 100644 index 0000000000..53dec8f1d2 --- /dev/null +++ b/db/migrations/state/0002.sql @@ -0,0 +1,62 @@ +-- +migrate Up +ALTER TABLE state.proof +ADD COLUMN prover_id VARCHAR; +UPDATE state.proof +SET prover_id = prover; +UPDATE state.proof +SET prover = NULL; +ALTER TABLE state.proof +ADD COLUMN created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(); +ALTER TABLE state.proof +ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(); +ALTER TABLE state.proof +ADD COLUMN generating_since TIMESTAMP WITH TIME ZONE; +UPDATE state.proof +SET generating_since = NOW() WHERE generating IS TRUE; +ALTER TABLE state.proof +DROP COLUMN IF EXISTS generating; + +CREATE INDEX IF NOT EXISTS transaction_l2_block_num_idx ON state.transaction (l2_block_num); +CREATE INDEX IF NOT EXISTS l2block_batch_num_idx ON state.l2block (batch_num); +CREATE INDEX IF NOT EXISTS l2block_received_at_idx ON state.l2block (received_at); +CREATE INDEX IF NOT EXISTS batch_timestamp_idx ON state.batch ("timestamp"); +CREATE INDEX IF NOT EXISTS log_tx_hash_idx ON state.log (tx_hash); +CREATE INDEX IF NOT EXISTS log_address_idx ON state.log (address); + +ALTER TABLE state.virtual_batch +ADD COLUMN sequencer_addr VARCHAR DEFAULT '0x0000000000000000000000000000000000000000'; + +CREATE TABLE IF NOT EXISTS state.trusted_reorg +( + timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + batch_num BIGINT, + reason VARCHAR NOT NULL +); + +-- +migrate Down +UPDATE state.proof +SET prover = prover_id; +ALTER TABLE state.proof +DROP COLUMN IF EXISTS prover_id; +ALTER TABLE state.proof +DROP COLUMN IF EXISTS created_at; +ALTER TABLE state.proof +DROP COLUMN IF EXISTS updated_at; +ALTER TABLE state.proof +ADD COLUMN generating BOOLEAN DEFAULT FALSE; +UPDATE state.proof +SET generating = TRUE WHERE generating_since IS NOT NULL; +ALTER TABLE state.proof +DROP COLUMN IF EXISTS generating_since; + +DROP INDEX IF EXISTS state.transaction_l2_block_num_idx; +DROP INDEX IF EXISTS state.l2block_batch_num_idx; +DROP INDEX IF EXISTS state.l2block_received_at_idx; +DROP INDEX IF EXISTS state.batch_timestamp_idx; +DROP INDEX IF EXISTS state.log_tx_hash_idx; +DROP INDEX IF EXISTS state.log_address_idx; + +ALTER TABLE state.virtual_batch +DROP COLUMN IF EXISTS sequencer_addr; + +DROP TABLE IF EXISTS state.trusted_reorg; diff --git a/db/migrations/state/0002_test.go b/db/migrations/state/0002_test.go new file mode 100644 index 0000000000..1610f45692 --- /dev/null +++ b/db/migrations/state/0002_test.go @@ -0,0 +1,139 @@ +package migrations_test + +import ( + "database/sql" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +// this migration changes length of the token name +type migrationTest0002 struct{} + +func (m migrationTest0002) InsertData(db *sql.DB) error { + // Insert block to respect the FKey + const addBlock = "INSERT INTO state.block (block_num, received_at, block_hash) VALUES ($1, $2, $3)" + if _, err := db.Exec(addBlock, 1, time.Now(), "0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"); err != nil { + return err + } + // Insert batches + for i := 0; i < 4; i++ { + _, err := db.Exec(`INSERT INTO state.batch (batch_num, global_exit_root, local_exit_root, state_root, acc_input_hash, timestamp, coinbase, raw_txs_data) + VALUES ($1, '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', + '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', + $2, '0x2536C2745Ac4A584656A830f7bdCd329c94e8F30', $3)`, i, time.Now(), common.HexToHash("0x29e885edaf8e0000000000000000a23cf2d7d9f1")) + if err != nil { + return err + } + } + // Insert proof + const insertProof = `INSERT INTO state.proof ( + batch_num, batch_num_final, proof, proof_id, input_prover, prover, generating + ) VALUES ( + 1, 1, '{"test": "test"}','proof_identifier','{"test": "test"}','prover 1', true + );` + _, err := db.Exec(insertProof) + if err != nil { + return err + } + // Insert virtual batch + const insertVirtualBatch = `INSERT INTO state.virtual_batch ( + batch_num, tx_hash, coinbase, block_num + ) VALUES ( + 1, '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x514910771af9ca656af840dff83e8264ecf986ca', 1);` + _, err = db.Exec(insertVirtualBatch) + if err != nil { + return err + } + return nil +} + +var indexes = []string{"transaction_l2_block_num_idx", "l2block_batch_num_idx", "l2block_received_at_idx", + "batch_timestamp_idx", "log_tx_hash_idx", "log_address_idx"} + +func (m migrationTest0002) RunAssertsAfterMigrationUp(t *testing.T, db *sql.DB) { + for _, idx := range indexes { + // getIndex + const getIndex = `SELECT count(*) FROM pg_indexes WHERE indexname = $1;` + row := db.QueryRow(getIndex, idx) + var result int + assert.NoError(t, row.Scan(&result)) + assert.Equal(t, 1, result) + } + // Insert new proof + const insertNewProof = `INSERT INTO state.proof ( + batch_num, batch_num_final, proof, proof_id, input_prover, prover, generating_since, prover_id, updated_at, created_at + ) VALUES ( + 2, 2, '{"test": "test"}','proof_identifier','{"test": "test"}','prover 1', $1, 'prover identifier', $1, $1 + );` + _, err := db.Exec(insertNewProof, time.Now()) + assert.NoError(t, err) + const insertOldProof = `INSERT INTO state.proof ( + batch_num, batch_num_final, proof, proof_id, input_prover, prover, generating + ) VALUES ( + 3, 3, '{"test": "test"}','proof_identifier','{"test": "test"}','prover 1', true + );` + _, err = db.Exec(insertOldProof) + assert.Error(t, err) + // Insert virtual batch + const insertVirtualBatch = `INSERT INTO state.virtual_batch ( + batch_num, tx_hash, coinbase, block_num, sequencer_addr) + VALUES (2, '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x514910771af9ca656af840dff83e8264ecf986ca', 1, '0x514910771af9ca656af840dff83e8264ecf986ca');` + _, err = db.Exec(insertVirtualBatch) + assert.NoError(t, err) + // Insert reorg + const insertReorg = `INSERT INTO state.trusted_reorg (batch_num, reason) + VALUES (2, 'reason of the trusted reorg');` + _, err = db.Exec(insertReorg) + assert.NoError(t, err) +} + +func (m migrationTest0002) RunAssertsAfterMigrationDown(t *testing.T, db *sql.DB) { + for _, idx := range indexes { + // getIndex + const getIndex = `SELECT count(*) FROM pg_indexes WHERE indexname = $1;` + row := db.QueryRow(getIndex, idx) + var result int + assert.NoError(t, row.Scan(&result)) + assert.Equal(t, 0, result) + } + // Insert new proof + const insertNewProof = `INSERT INTO state.proof ( + batch_num, batch_num_final, proof, proof_id, input_prover, prover, generating_since, prover_id, updated_at, created_at + ) VALUES ( + 3, 3, '{"test": "test"}','proof_identifier','{"test": "test"}','prover 1', $1, 'prover identifier', $1, $1 + );` + _, err := db.Exec(insertNewProof, time.Now()) + assert.Error(t, err) + const insertOldProof = `INSERT INTO state.proof ( + batch_num, batch_num_final, proof, proof_id, input_prover, prover, generating + ) VALUES ( + 3, 3, '{"test": "test"}','proof_identifier','{"test": "test"}','prover 1', true + );` + _, err = db.Exec(insertOldProof) + assert.NoError(t, err) + // Insert virtual batch + insertVirtualBatch := `INSERT INTO state.virtual_batch ( + batch_num, tx_hash, coinbase, block_num, sequencer_addr, + ) VALUES ( + 3, '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x514910771af9ca656af840dff83e8264ecf986ca', 1, '0x514910771af9ca656af840dff83e8264ecf986ca');` + _, err = db.Exec(insertVirtualBatch) + assert.Error(t, err) + // Insert virtual batch + insertVirtualBatch = `INSERT INTO state.virtual_batch ( + batch_num, tx_hash, coinbase, block_num) + VALUES (3, '0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1', '0x514910771af9ca656af840dff83e8264ecf986ca', 1);` + _, err = db.Exec(insertVirtualBatch) + assert.NoError(t, err) + // Insert reorg + const insertReorg = `INSERT INTO state.trusted_reorg (batch_num, reason) + VALUES (2, 'reason of the trusted reorg');` + _, err = db.Exec(insertReorg) + assert.Error(t, err) +} + +func TestMigration0002(t *testing.T) { + runMigrationTest(t, 2, migrationTest0002{}) +} diff --git a/db/migrations/state/0003.sql b/db/migrations/state/0003.sql new file mode 100644 index 0000000000..eda0f996f5 --- /dev/null +++ b/db/migrations/state/0003.sql @@ -0,0 +1,8 @@ +-- +migrate Up +ALTER TABLE state.log +ALTER COLUMN topic0 DROP NOT NULL; + +-- +migrate Down +DELETE FROM state.log WHERE topic0 IS NULL; +ALTER TABLE state.log +ALTER COLUMN topic0 SET NOT NULL; \ No newline at end of file diff --git a/db/migrations/state/0004.sql b/db/migrations/state/0004.sql new file mode 100644 index 0000000000..6bf54ea4ae --- /dev/null +++ b/db/migrations/state/0004.sql @@ -0,0 +1,12 @@ +-- +migrate Up +CREATE TABLE state.event +( + event_type VARCHAR NOT NULL, + timestamp TIMESTAMP WITH TIME ZONE NOT NULL, + ip VARCHAR, + tx_hash VARCHAR, + payload VARCHAR +); + +-- +migrate Down +DROP table state.event; diff --git a/db/migrations/state/0005.sql b/db/migrations/state/0005.sql new file mode 100644 index 0000000000..60e2e057af --- /dev/null +++ b/db/migrations/state/0005.sql @@ -0,0 +1,20 @@ +-- +migrate Up +DROP table state.event; +DROP table state.debug; + +-- +migrate Down +CREATE TABLE IF NOT EXISTS state.event +( + event_type VARCHAR NOT NULL, + timestamp TIMESTAMP WITH TIME ZONE NOT NULL, + ip VARCHAR, + tx_hash VARCHAR, + payload VARCHAR +); + +CREATE TABLE IF NOT EXISTS state.debug +( + error_type VARCHAR, + timestamp timestamp, + payload VARCHAR +); diff --git a/db/migrations/state/0006.sql b/db/migrations/state/0006.sql new file mode 100644 index 0000000000..0f2b9ca341 --- /dev/null +++ b/db/migrations/state/0006.sql @@ -0,0 +1,9 @@ +-- +migrate Up +ALTER TABLE state.batch + ADD COLUMN batch_resources JSONB, + ADD COLUMN closing_reason VARCHAR; + +-- +migrate Down +ALTER TABLE state.batch + DROP COLUMN batch_resources, + DROP COLUMN closing_reason; \ No newline at end of file diff --git a/db/migrations/state/utils_test.go b/db/migrations/state/utils_test.go new file mode 100644 index 0000000000..4284614d5e --- /dev/null +++ b/db/migrations/state/utils_test.go @@ -0,0 +1,118 @@ +package migrations_test + +import ( + "database/sql" + "fmt" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/gobuffalo/packr/v2" + "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v4/stdlib" + migrate "github.com/rubenv/sql-migrate" + "github.com/stretchr/testify/require" +) + +/* + Considerations tricks and tips for migration file testing: + + - Functionality of the DB is tested by the rest of the packages, migration tests only have to check persistence across migrations (both UP and DOWN) + - It's recommended to use real data (from testnet/mainnet), but modifying NULL fields to check that those are migrated properly + - It's recommended to use some SQL tool (such as DBeaver) that generates insert queries from existing rows + - Any new migration file could be tested using the existing `migrationTester` interface. Check `0002_test.go` for an example +*/ + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stderr"}, + }) +} + +type migrationTester interface { + // InsertData used to insert data in the affected tables of the migration that is being tested + // data will be inserted with the schema as it was previous the migration that is being tested + InsertData(*sql.DB) error + // RunAssertsAfterMigrationUp this function will be called after running the migration is being tested + // and should assert that the data inserted in the function InsertData is persisted properly + RunAssertsAfterMigrationUp(*testing.T, *sql.DB) + // RunAssertsAfterMigrationDown this function will be called after reverting the migration that is being tested + // and should assert that the data inserted in the function InsertData is persisted properly + RunAssertsAfterMigrationDown(*testing.T, *sql.DB) +} + +var ( + stateDBCfg = dbutils.NewStateConfigFromEnv() + packrMigrations = map[string]*packr.Box{ + db.StateMigrationName: packr.New(db.StateMigrationName, "./migrations/state"), + db.PoolMigrationName: packr.New(db.PoolMigrationName, "./migrations/pool"), + } +) + +func runMigrationTest(t *testing.T, migrationNumber int, miter migrationTester) { + // Initialize an empty DB + d, err := initCleanSQLDB() + require.NoError(t, err) + require.NoError(t, runMigrationsDown(d, 0, db.StateMigrationName)) + // Run migrations until migration to test + require.NoError(t, runMigrationsUp(d, migrationNumber-1, db.StateMigrationName)) + // Insert data into table(s) affected by migration + require.NoError(t, miter.InsertData(d)) + // Run migration that is being tested + require.NoError(t, runMigrationsUp(d, 1, db.StateMigrationName)) + // Check that data is persisted properly after migration up + miter.RunAssertsAfterMigrationUp(t, d) + // Revert migration to test + require.NoError(t, runMigrationsDown(d, 1, db.StateMigrationName)) + // Check that data is persisted properly after migration down + miter.RunAssertsAfterMigrationDown(t, d) +} + +func initCleanSQLDB() (*sql.DB, error) { + // run migrations + if err := db.RunMigrationsDown(stateDBCfg, db.StateMigrationName); err != nil { + return nil, err + } + c, err := pgx.ParseConfig(fmt.Sprintf("postgres://%s:%s@%s:%s/%s", stateDBCfg.User, stateDBCfg.Password, stateDBCfg.Host, stateDBCfg.Port, stateDBCfg.Name)) + if err != nil { + return nil, err + } + sqlDB := stdlib.OpenDB(*c) + return sqlDB, nil +} + +func runMigrationsUp(d *sql.DB, n int, packrName string) error { + box, ok := packrMigrations[packrName] + if !ok { + return fmt.Errorf("packr box not found with name: %v", packrName) + } + + var migrations = &migrate.PackrMigrationSource{Box: box} + nMigrations, err := migrate.ExecMax(d, "postgres", migrations, migrate.Up, n) + if err != nil { + return err + } + if nMigrations != n { + return fmt.Errorf("Unexpected amount of migrations: expected: %d, actual: %d", n, nMigrations) + } + return nil +} + +func runMigrationsDown(d *sql.DB, n int, packrName string) error { + box, ok := packrMigrations[packrName] + if !ok { + return fmt.Errorf("packr box not found with name: %v", packrName) + } + + var migrations = &migrate.PackrMigrationSource{Box: box} + nMigrations, err := migrate.ExecMax(d, "postgres", migrations, migrate.Down, n) + if err != nil { + return err + } + if nMigrations != n { + return fmt.Errorf("Unexpected amount of migrations: expected: %d, actual: %d", n, nMigrations) + } + return nil +} diff --git a/db/scripts/init_event_db.sql b/db/scripts/init_event_db.sql new file mode 100644 index 0000000000..c45a6ba1c0 --- /dev/null +++ b/db/scripts/init_event_db.sql @@ -0,0 +1,14 @@ +CREATE TYPE level_t AS ENUM ('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug'); + +CREATE TABLE public.event ( + id BIGSERIAL PRIMARY KEY, + received_at timestamp WITH TIME ZONE default CURRENT_TIMESTAMP, + ip_address inet, + source varchar(32) not null, + component varchar(32), + level level_t not null, + event_id varchar(32) not null, + description text, + data bytea, + json jsonb +); diff --git a/db/scripts/init_prover_db.sql b/db/scripts/init_prover_db.sql new file mode 100644 index 0000000000..e089270601 --- /dev/null +++ b/db/scripts/init_prover_db.sql @@ -0,0 +1,14 @@ +CREATE DATABASE prover_db; +\connect prover_db; + +CREATE SCHEMA state; + +CREATE TABLE state.nodes (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); +CREATE TABLE state.program (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); + +CREATE USER prover_user with password 'prover_pass'; +GRANT CONNECT ON DATABASE prover_db TO prover_user; +ALTER USER prover_user SET SEARCH_PATH=state; +GRANT ALL PRIVILEGES ON SCHEMA state TO prover_user; +GRANT ALL PRIVILEGES ON TABLE state.nodes TO prover_user; +GRANT ALL PRIVILEGES ON TABLE state.program TO prover_user; diff --git a/db/scripts/single_db_server.sql b/db/scripts/single_db_server.sql new file mode 100644 index 0000000000..3151ed589e --- /dev/null +++ b/db/scripts/single_db_server.sql @@ -0,0 +1,17 @@ +CREATE DATABASE state_db; +CREATE DATABASE pool_db; +CREATE DATABASE rpc_db; + +CREATE DATABASE prover_db; +\connect prover_db; + +CREATE SCHEMA state; + +CREATE TABLE state.nodes (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); +CREATE TABLE state.program (hash BYTEA PRIMARY KEY, data BYTEA NOT NULL); + +CREATE USER prover_user with password 'prover_pass'; +GRANT CONNECT ON DATABASE prover_db TO prover_user; +GRANT USAGE ON SCHEMA state TO prover_user; +GRANT ALL PRIVILEGES ON TABLE state.nodes TO prover_user; +GRANT ALL PRIVILEGES ON TABLE state.program TO prover_user; \ No newline at end of file diff --git a/db/single_db_server.sql b/db/single_db_server.sql deleted file mode 100644 index eb8cd7dd87..0000000000 --- a/db/single_db_server.sql +++ /dev/null @@ -1,3 +0,0 @@ -CREATE DATABASE state_db; -CREATE DATABASE pool_db; -CREATE DATABASE rpc_db; diff --git a/docker-compose.yml b/docker-compose.yml index e62dd94e7f..4aee732f21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,321 +3,116 @@ networks: default: name: zkevm services: - zkevm-sequencer: - container_name: zkevm-sequencer - image: zkevm-node - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_POOL_HOST=zkevm-pool-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./${CONFIG_MODE}/config/config.${CONFIG_MODE:-local}.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components sequencer" - - zkevm-json-rpc: - container_name: zkevm-json-rpc - image: zkevm-node - ports: - - 8123:8123 - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_POOL_HOST=zkevm-pool-db - - ZKEVM_NODE_RPC_DB_HOST=zkevm-rpc-db - - ZKEVM_NODE_RPC_BROADCASTURI=zkevm-broadcast:61090 - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./${CONFIG_MODE}/config/config.${CONFIG_MODE:-local}.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components rpc" - - zkevm-non-sequencer-json-rpc: - container_name: zkevm-non-sequencer-json-rpc + zkevm-rpc: + container_name: zkevm-rpc + restart: unless-stopped + depends_on: + zkevm-pool-db: + condition: service_healthy + zkevm-state-db: + condition: service_healthy + zkevm-sync: + condition: service_started image: zkevm-node + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 512M ports: - - 8125:8125 - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_POOL_HOST=zkevm-pool-db - - ZKEVM_NODE_RPC_DB_HOST=zkevm-rpc-db - - ZKEVM_NODE_RPC_SEQUENCERNODEURI=http://zkevm-json-rpc:8123 - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./${CONFIG_MODE}/config/config.${CONFIG_MODE:-local}.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components rpc" - - zkevm-aggregator: - container_name: zkevm-aggregator - image: zkevm-node + - 8545:8545 + - 9091:9091 # needed if metrics enabled environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore + - ZKEVM_NODE_ETHERMAN_URL=${ZKEVM_NODE_ETHERMAN_URL} volumes: - - ./test/test.keystore:/pk/keystore - - ./${CONFIG_MODE}/config/config.${CONFIG_MODE:-local}.toml:/app/config.toml + - ${ZKEVM_ADVANCED_CONFIG_DIR:-./config/environments/public}/public.node.config.toml:/app/config.toml command: - "/bin/sh" - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components aggregator" + - "/app/zkevm-node run --network ${ZKEVM_NETWORK} --cfg /app/config.toml --components rpc" zkevm-sync: container_name: zkevm-sync + restart: unless-stopped + depends_on: + zkevm-state-db: + condition: service_healthy image: zkevm-node + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 512M environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./${CONFIG_MODE}/config/config.${CONFIG_MODE:-local}.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components synchronizer" - - zkevm-broadcast: - container_name: zkevm-broadcast - image: zkevm-node - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - ports: - - 61090:61090 + - ZKEVM_NODE_ETHERMAN_URL=${ZKEVM_NODE_ETHERMAN_URL} volumes: - - ./config/config.local.toml:/app/config.toml - - ./test/test.keystore:/pk/keystore + - ${ZKEVM_ADVANCED_CONFIG_DIR:-./config/environments/public}/public.node.config.toml:/app/config.toml command: - "/bin/sh" - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components broadcast-trusted-state" + - "/app/zkevm-node run --network ${ZKEVM_NETWORK} --cfg /app/config.toml --components synchronizer" zkevm-state-db: container_name: zkevm-state-db + restart: unless-stopped image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 ports: - 5432:5432 volumes: - - ./config/initproverdb.sql:/docker-entrypoint-initdb.d/init.sql + - ./db/scripts/init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql + - ${ZKEVM_NODE_STATEDB_DATA_DIR}:/var/lib/postgresql/data + - ${ZKEVM_ADVANCED_CONFIG_DIR:-./config/environments/public}/postgresql.conf:/etc/postgresql.conf environment: - POSTGRES_USER=state_user - POSTGRES_PASSWORD=state_password - POSTGRES_DB=state_db - command: ["postgres", "-N", "500"] + command: + - "postgres" + - "-N" + - "500" + - "-c" + - "config_file=/etc/postgresql.conf" zkevm-pool-db: container_name: zkevm-pool-db + restart: unless-stopped image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 ports: - 5433:5432 + volumes: + - ${ZKEVM_NODE_POOLDB_DATA_DIR}:/var/lib/postgresql/data environment: - POSTGRES_USER=pool_user - POSTGRES_PASSWORD=pool_password - POSTGRES_DB=pool_db - command: ["postgres", "-N", "500"] - - zkevm-rpc-db: - container_name: zkevm-rpc-db - image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G - ports: - - 5434:5432 - environment: - - POSTGRES_USER=rpc_user - - POSTGRES_PASSWORD=rpc_password - - POSTGRES_DB=rpc_db - command: ["postgres", "-N", "500"] - - zkevm-explorer-l1: - container_name: zkevm-explorer-l1 - image: hermeznetwork/hermez-node-blockscout:latest - ports: - - 4000:4000 - environment: - - NETWORK=ETH - - SUBNETWORK=Local Ethereum - - COIN=ETH - - ETHEREUM_JSONRPC_VARIANT=geth - - ETHEREUM_JSONRPC_HTTP_URL=http://zkevm-mock-l1-network:8545 - - DATABASE_URL=postgres://l1_explorer_user:l1_explorer_password@zkevm-explorer-l1-db:5432/l1_explorer_db - - ECTO_USE_SSL=false - - MIX_ENV=prod - command: - ["/bin/sh", "-c", "mix do ecto.create, ecto.migrate; mix phx.server"] - - zkevm-explorer-l1-db: - container_name: zkevm-explorer-l1-db - image: postgres - ports: - - 5435:5432 - environment: - - POSTGRES_USER=l1_explorer_user - - POSTGRES_PASSWORD=l1_explorer_password - - POSTGRES_DB=l1_explorer_db - command: ["postgres", "-N", "500"] - - zkevm-explorer-l2: - container_name: zkevm-explorer-l2 - image: hermeznetwork/hermez-node-blockscout:latest - ports: - - 4001:4000 - environment: - - NETWORK=POE - - SUBNETWORK=Polygon Hermez - - COIN=ETH - - ETHEREUM_JSONRPC_VARIANT=geth - - ETHEREUM_JSONRPC_HTTP_URL=http://zkevm-explorer-json-rpc:8124 - - DATABASE_URL=postgres://l2_explorer_user:l2_explorer_password@zkevm-explorer-l2-db:5432/l2_explorer_db - - ECTO_USE_SSL=false - - MIX_ENV=prod - - LOGO=/images/blockscout_logo.svg - - LOGO_FOOTER=/images/blockscout_logo.svg command: - ["/bin/sh", "-c", "mix do ecto.create, ecto.migrate; mix phx.server"] - - zkevm-explorer-json-rpc: - container_name: zkevm-explorer-json-rpc - image: zkevm-node - ports: - - 8124:8124 - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_POOL_HOST=zkevm-pool-db - - ZKEVM_NODE_RPC_DB_HOST=zkevm-rpc-db - - ZKEVM_NODE_RPC_PORT=8124 - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./config/config.local.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components rpc --http.api eth,net,debug,zkevm,txpool,web3" - - zkevm-explorer-l2-db: - container_name: zkevm-explorer-l2-db - image: postgres - ports: - - 5436:5432 - environment: - - POSTGRES_USER=l2_explorer_user - - POSTGRES_PASSWORD=l2_explorer_password - - POSTGRES_DB=l2_explorer_db - command: ["postgres", "-N", "500"] - - zkevm-mock-l1-network: - container_name: zkevm-mock-l1-network - image: hermeznetwork/geth-zkevm-contracts@sha256:24754a773b803ce0de8278c02bb756757b09fda65dc993e560a0b76a09b88248 - ports: - - 8545:8545 - command: ["--http", "--http.api", "admin,eth,debug,miner,net,txpool,personal,web3", "--http.addr", "0.0.0.0","--http.corsdomain", "*", "--http.vhosts" ,"*", "--ws", "--ws.origins", "*", "--ws.addr", "0.0.0.0", "--dev", "--datadir", "/geth_data", "--syncmode", "full"] + - "postgres" + - "-N" + - "500" zkevm-prover: container_name: zkevm-prover - image: hermeznetwork/zkevm-prover:develop@sha256:408855e37f4751260bfb206e6aeb3b53c773a1615e8d675166b3647770700701 + restart: unless-stopped + image: hermeznetwork/zkevm-prover:v1.1.3-RC2-fork.4 + depends_on: + zkevm-state-db: + condition: service_healthy ports: - # - 50051:50051 # Prover - - 50052:50052 # Mock prover - 50061:50061 # MT - 50071:50071 # Executor volumes: - - ./${CONFIG_MODE}/config/prover.config.${CONFIG_MODE:-local}.json:/usr/src/app/config.json + - ${ZKEVM_ADVANCED_CONFIG_DIR:-./config/environments/public}/public.prover.config.json:/usr/src/app/config.json command: > zkProver -c /usr/src/app/config.json - - zkprover-mock: - container_name: zkprover-mock - image: hermeznetwork/zkprover-mock:latest - ports: - - 43061:43061 # MT - - 43071:43071 # Executor - volumes: - - ./test/vectors/src:/app/testvectors - command: > - /app/zkprover-mock server --statedb-port 43061 --executor-port 43071 --test-vector-path /app/testvectors - - zkevm-approve: - container_name: zkevm-approve - image: zkevm-node - environment: - - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - volumes: - - ./test/test.keystore:/pk/keystore - - ./config/config.local.toml:/app/config.toml - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node approve --am 10000000000000000 -y --network local --cfg /app/config.toml" - - zkevm-permissionless-db: - container_name: zkevm-permissionless-db - image: postgres - deploy: - resources: - limits: - memory: 2G - reservations: - memory: 1G - ports: - - 5437:5432 - environment: - - POSTGRES_USER=test_user - - POSTGRES_PASSWORD=test_password - - POSTGRES_DB=test_db - command: ["postgres", "-N", "500"] - - zkevm-permissionless-node: - container_name: zkevm-permissionless-node - image: zkevm-node - ports: - - 8126:8126 - environment: - - ZKEVM_NODE_TRUSTED=false - - ZKEVM_NODE_STATEDB_USER=test_user - - ZKEVM_NODE_STATEDB_PASSWORD=test_password - - ZKEVM_NODE_STATEDB_NAME=state_db - - ZKEVM_NODE_STATEDB_HOST=zkevm-permissionless-db - - ZKEVM_NODE_POOL_USER=test_user - - ZKEVM_NODE_POOL_PASSWORD=test_password - - ZKEVM_NODE_POOL_NAME=pool_db - - ZKEVM_NODE_POOL_HOST=zkevm-permissionless-db - - ZKEVM_NODE_RPC_DB_USER=test_user - - ZKEVM_NODE_RPC_DB_PASSWORD=test_password - - ZKEVM_NODE_RPC_DB_NAME=rpc_db - - ZKEVM_NODE_RPC_DB_HOST=zkevm-permissionless-db - - ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH=/pk/keystore - - ZKEVM_NODE_RPC_PORT=8126 - volumes: - - ./test/test.keystore:/pk/keystore - - ./config/config.local.toml:/app/config.toml - - ./config/single_db_server.sql:/docker-entrypoint-initdb.d/init.sql - command: - - "/bin/sh" - - "-c" - - "/app/zkevm-node run --network local --cfg /app/config.toml --components \"rpc,synchronizer\"" diff --git a/docs/architecture.drawio.png b/docs/architecture.drawio.png index 2f54d8b1a58b71772452e97774f23946b0302b21..6b6510c17f9d28fb015e17b0f2bcca4fbb5f020b 100644 GIT binary patch delta 74233 zcmce;byU>d+cydW$N(Y(k|HtEEg&g5(v7rq3ld8AmlQ;hE@>nrltw_1QaY576p;o& zy2E#mxA*T^?>gss*EwsQ^Q<+0z%aAFyRK_rpV*{E;kVV|#WG^Pj$`s5{p>Ju_`%!K|MbO|rWNMZbf;6p44Io!C_r4*@{lGaXE(k?E}p5QS~&Q8`${3!5_ zoSlOMc;hzs&DG7^#qHluSUQ-yy4qR(`!@Jkf;25M;rk8xYCo#qSO0XRl=+{hlC#)g zCMZ%}Pk4l2PiSCW|M%zWIX0bt`e)5?Bf%7hA%UAjJzbrbVOw9lMmVh8Yq}YmJ8m6d!CL5V}HDsR- z4r2O40s|v3F=gYBn51oiDo-PFu9EQP5nE_TvS>)lK9Q1^)MumsS=o#mYqVc$NSEloVHbGxH4(Jjy%lhD*Y0as+MS1==`Uj^P~+Gi zE)EUbQcr)q-?EylvaYfpV;9Ks*qma*y>>I!0{RrG*x<61uav}&V_B^EO3r0D%~mOa zS=DI#deZfnJVd0D-j~7G#DVbjnTF~a->qgot8PS^m^a@ijZslv?bO6Gkn&I@4u2GJcwsE{m_)iX>fmAJUu&`XZoFU%E8a^zTPB` zrErKYK!c~z`NN6a;l?Bbji_5J0e8JrqsQjU0^Q0f2a;6bCwVv2wF*_@7GB&{dnx41 z9ZfBi-01#O>CJ=M(INT(`e6E}^pS#2Gp{>`hYOUg+k$a+55`SPv)wl)G@}cCeS2?P zt(Y~Yid>{pBA0>vX2_9^C6^rhoj``icq=dk8eE8x?VrLgAZ=+jnnDI*Ql zA>Z+=Z|^<(=GsD*D!XVCE-%jd1jdaRShD@9Jjp1TxQyyGvV4Duc%QBnE!9msCHVeo zkOzykq-@N2=PtHxxd|7M#Bt8~0^RRe3IEe>9X;a$F-a4;ZBp^y=X<-03F^JyFAs$p z!0aWy&dsIN;*6N1o1~@s)f`^5N#RZNZoq*!K|%dZYQiG3ppR6Z55&$%}28Y;@3E_TkWeVB6Fic5xUe($Metm z9H;IiCB=8eVaINlsiq4;?6zGeE7|H|ytn3Ry>=R#D05%vXvHQ`;0f{?BbKqAC?D@l z+GdAM_Gi=*j+l2}z1ZoZlYfdyjz!P*kg}*}m>i{$bH}ptYQxELx=wp}PO_g|;kfML zN;Z^CBzdkO7kz^XMC$!#Z@gr(15NWjmAkxB7o+8p`fbr@x7?ow#XbD&44oNzA5Pki zRX>;ag45qV{UT4Nb1mYwS~wF!m>r++l~@)I2h34BJY+-;&0UYj?m?fLgKpAH;6_+< z!ydrZ4-CtWjRW9u%TbC7@%k+R{%!FmtT(%HL%8nJdN0PYrlwyPw0I`g6uEsRjP3Rm zmmju92S;f0V0%r?Ec5_wE_zk*<>kc|^xpCA(3vD`0)tqwNLZD807;yvfLD_B@DSzp zMs9|%Fui>r#u~*ernh};SkGO&$JzhbTgVuDbpfu;~-ko=EU?JIRBQeVwz zCs_iczHDP7=OostBCGo)*jvF zFKcP5`jOv$JSSz#^LQ3B%nK4U*~|dLd+Z9)GLY!)nVG4nUNt+3^J!QT_yyRq_um?cNNnA^ z%@|ie#alQb%D|0VH!oGjTV-y0mV>~r$7KzLUCEMmHz!7#S2AEFHfhT|-U{bZsHu4I zC8$Aj&*GC~#l`VLOfZ?>qw%+dR#;;>$L77YJ_qZ&7Z5nzKyoD2uEqPAi@>Lp4AW?B z9Vz2>m}hV}%zq|O#M99nV?Cs4AaFQg8B<&^NQ#=IsRJ?a{w6qhyWFV3rDVkaLOd+C z+)Er{6D!MODD&`!iR0q8HA7zwY-O2aG(c1>m6m_VL-g)W$Qb?FUmJnQs6(&Lc@e2) ziXOlTh{GefgyKJu{Am2(f7T08>P^+7^Qa{DIJ1xtgN6??Sf0){`^divA!H#^sZ8iiCL)+B_|{#$e!S&9~# z)tFcEePRE#thh;V@Q8IbS7_GjmAzOecPMY6@{XF?{@|yxTHB$lbwAt59x;?Kg?E_E zz{{jD)d(;p`@5=}o&0wxenWB?RH0Xc5tVo}M!{XQzGW^{Fp0}f?+0+l*(L+`U#Yy7 zGDH|!4^PAw*+S2mGfYkp6krf>iV4h$pjH~@U~DbTvvCf5h%!w2aMbbPOw8niKG#!1 zzLTcjUys{sCT1F3$KLmP=aZlwleV5kY;tbTo~;#SkDh&ABW^zB+jPRL%#$wf*$Y%e7G}snY zZR~PzytMuX`AwR3KZYEX@Q(){v2(Eweh*a5;h?%KQ74BgQP)cZKC)uj|u-RW?vg@{lD zJ1CoiR@gc$yHm#_)C7k(`W=e`!)+A@`;oPXWo z*7{-iqdUisqP@2)Pw__7jww6psF{=!x8LoO7HomSle^{IrR_Ol#8dV;c>$u=J|4w$NZ^T2tbDLpfg3EMA>drf0wWISb_JH&(yA zD)2u$G_dOi#TTd0H@5`*2eMZqytloRlDIXKZauptxYqpRDK$8g5FBv7t{^r(FP97y z>m)wkNYGq{!4rI>!&$DaBmFN&aa4@tWj&`!6D0hohm3(C^m7~nbu{A|BlTu|B3p(R zC3=V(TwFnkyo&Fd#UBx9C!t?;WXAi*gMl{Vt(kxGh`)nchfS%w(^LZ2wEh-^$N2up z6uNLvV$KICZXJv3_2%=6C88{7tNAFaSJQQ^Amy^8^th>ab~WsFXMLcQs$2dp{Kt_e z^vylxDz%`>CwTLAI|2Kg2oKLz#L}KkRO}0^_C&72&iJrYQsz(%iP`rN941DhHUnt-qzwL;^r#4F}LDgP-qIwnnEy!m~KX$|-O#Eu~my?DEMTTEuRp4ne8K$a} zR_k@flQq04Ke<)3H)fj+o88<`0cUlBea@ugR=<0B<~T8-0= zHNq9RIO#O<#89jkBkGbmr5*ia57c-D#!aC&dO)?J{hbV< znTY@bEC*Y^5=}+yEm8|Q#4Zn{mr@WJb@wEvI(`3OES_4C;dXg`f`fTpaSs|O*nM#S zs6I{^RCK(E>9-024BX|o4IaTDu?YX zbd?@o^Rs3UB(ZpJ-tp9By|}1^=6$Jl@vWu4l$3ZTZ_NMvsGxTzZ)74Y7p6qX(RN7es#Hk@A=r;gnNw==NX85{vJ( z24UI%Xa%65dKiYE8(6v5MsoY{t47K5A4J1-j)np_Kb9YJg!VHP7Dlu+`I#HO7d9Rf zEhMb_0T9+y@lw7hM4`Y(;hk5P6KxuBQs8%avf}iz*A+$|+tWCk>hf*yHsT} zaD&N<-mhYw09Q9lno^oR^Km<#OD|i|>jBZq8@RXFGa0U@j}*s@pT|hOtsJuPWebIU z*sGeH#1s;68=JJT@&LUEL=_?UT(w0kr!ZJ2Nwic<>2z8syvrP-t+K~zgJN!zcU+?H_&!i0@d=$bxYO_#@|DRW>E1poAi*m9j>-F#tPTo)Zl);7s(~46Lucke$TX0=Qf>~$JG;2h- zUvZ3;ROU=keLUk|(Tf&I`S{9php&x5#yS3mb~vsk(VyLI98Uek%xR`n`J+v6H+EE# zvHr^vSI1Qy%fbjx2`QDfEt_Y>16bXvzW23$KvV%F5%bM-vgsEa9rS%_N%E`;hUafN zR`%dbr|TZfk$k2KgA~ywSy6#fH^HILJrOiJ4;2|QCf8sR`c3(1 z1_tI7M1!NpX+HIQuRfLXGa)|tN=6FWPN|zWNa)zu6=g2_5^l*h`=Ur^vqiEErby`@ zK#8d|8>F&59vR`(n&s_n7z*Sykz(9F&k6a>0bUX>C~^PQ`l$MT*8t&1+~?FvZJF2Q zc=NaLG!$y79#d`-y*L!9`DV=ViIj zmpIYs>b2swp#i4uLN9|Vs~+MO{-IA>H4p{-#AtiV%78o5qHhL;sW{Lic5Jp2UnpcP ztD_<_=H%?dWCClz}G%iDvQJPYacv)hfAe1K=V^Gi(lU`Jzp!@*V}TZZJtSWt2grH>xh?7^X!4P zn{wozC3tlg72qhM8+8jJt!qf8I$=QkbR(I zDQX(oK;5(!C*3!2oTbf9Ir|D!3MKiLKJSdVLh-=@P6v%Y+V!jOQXPH2n|F&l&!Wgv z{CZ40U&GPBF_9{R!Oe(EsF|YFnZHtmwmJEm?)gDEltj+;;C1u+8Cp$W$l^y&nL+g; zIMO|)Wrl|O8WBo0A>5(L*%JPV<6R#YH*l2Jb1mp(SI@$#~{xhfiNjt z!J}o|ThS+prtuOHSUyQ5a1S!4pfZ2QGn$!hy}(CIwtVf!!>0k0(3+zG376;-lLWOr z(2dMfuK@rJC9tR$Ep&9u!>Q<=SH^M5v4Zit4vFh+f9MpHofNI&4*mRiWi&DCbU3Kj zX7v5ZdzrrH*SWepuf!j0eK#fKzS*N2eZtH2^z_)Q=c|UNsk8nkIsHu+b-{N-{fo2e zjP@!!SXDL_>gV4f<_lC+R?o-fnO}}u4`SAMH%#>>+G$owZ1*n6mXBB*I=-SNGsv~J zme7=0-5TF4rC?2fKlh1sC(rBB4rbAI8+DBfM3E1e)a!UiSA6U&*CK>VdO+^&&a{b} zMIZWX44qmoJldF>804b53#mSgM$6PpVEn-f1%B_Ku>0@^rll|5V41M_0xjBaNwizY zV{}^@%Q7E*phkwSo#POYlit45fi;Yi{%m0FYtPRYjN5=TDj9Gce{0M^#-STUnB_QK zhgaxP8Mloldd567;W$y*M9G0cw))0(vH(*JA?SF7;8reMEF>r!KkHjDv94=wqM32e zpn$2|%EM49(Ay@T*jL!TKX2!_SEMMxN!TQwoBlY{ycrsA6`o zKE_Vd-}3un3uPIW*G^O^-Axm^*eL+nk9IdsenqY3J?D=o@9&@8fCd2Gju0 zak~5=-c>pYBb%Wtt_d3C9~jFzk^N+@H7NICWG$lo`8nXRw0aW(G-jQHK*6Aor%3yS z0g)&S!1n5aR1KHY=GQn^ywmLtBJ0uDn)d04Ncxti zPb!v9nRL(Dh4e+sxTrAqd8(!@d)e`E<9k4nk~v(gRm2LVrt=GaK$m_7+ckD0`S%Ny z;_QyTzA-ESRY9;=z{CMkMScnek8Zs~HE;46nJ(yvuk{{fuAIcKqus@j6**#_yGk+? zwf&&R%Q(xH&{{f+q;*^jR>)I72UG7mXsq!3?yrYnjpp&B{lV~f+}M+?{4*$@Z%Qo0 z>yLi$hkTa^ZwNZ*uR07Wz{B1O+=;-3G0r7wXlj-~Bh8t|}6y@y&>aH)@O zYs0e4sxK42lA;R7<*$$ua?uA;OuRLIU)9)S1(|;fik9e0;-HvHArBw^4L9Sw0F!8M zI(S&l6&<_5vPE?`*8F*S!`u4uT%Z`c~TIIz! z!ZQ$rM8;-rc_u}O$f4%eWUI75!zT-eO`JmEW4KZn%4?FRs|-})J~i~Icc^h;PR@;M z%pw3`;3zM9%OqeVfBg=a&fsqlT?LtZ!Roau|KR^D*A~VP!UQN zyQCdPBMG(RIK2QwwO0vavaFe&%}2N>N3O&LD#Lm{UXzVg4ixd4f&f8oy*<~~%Mc>Q zq42?Lw}<5nH81)5Bt|Jd!syPnLhfvpb>HcI3W9-am}Sf%daHE5kHhJI5scUbcty-% zw(nEuhFokqLt3*rw>M~PlrvG?$&^DZm=xGGt3W2G>P5;DFT!r9$0c#-m9XJ_^rO#3 z&PT*nkoyLJ8a)Q$XY`akCn6EOl}l5oX+Ktyq*&P`xQHEaz9XO1O%XKuA8x(Wkoa}> zuOKrYv7yV8A*dJ7>pD_*Jko{N@)L%+_l=*;ioPB3jUGjnvC=(hSUfd0fBy9Kd;X5mom=R`CMQmDyuZ8mfR3SKg6;cEb zrj)!l6$(i4o**n-?MU2@r&1Xmd(~!bu#?lDG@`_m>Eq)d6U~v<9 z*JlPixBh^2`W_4@Pw3a&O9&$@_K~(&9JWH>pBKFoHf!ko*H;cic(E9NUV)Ebq^P%= zJ2E8nn15bD^~5=dNW+*a@xQG|!QSF&z#HT~U03|4kwENuIY6m9iT57>aH zc!Nxx@t;O8Ng}8*L2sb{y*vNoy@CGs?);DU2KqC}|IOt55A+85f4)@zzw`$ByK(57 zu#>rs*%vya6VxS6WIz$jc-QmS)$&RaCj)eJN{3u=85CJj7|Iea03wNqTIc{v&<06F z*dIb}G1GH4&bj46x6W~z8B}D6;Ji@)GE2Vm_Yady{Zopqwy=xSgM>=UuHG>{Q!cG0Wd{5W8&!RaWz~c6K*R);iQyt3i{sJ!KaeySfV`#41E*y~u)qMTkN`5QGDtQ{ z0N)oLKQmiFk$&@-cC32*1C=KH1j^Gc)#VC)lheb9aD>H?p;E8Z?{rcx6{MKNa~n4@ zZiWG-vj-pmZp+RnO{a&TRSFnjV`Bji-2*BiniS?Ghr3U&(Xel|{Ql7YQh>vjs^SM@ zEEg<}6m{%l4=Snt3=u8wp!+o2*J^>p`Qhx>-GhVv5bQiPj1hBh$lKfAK1^N=Zf0Mt zlE#<8{9N9%ij4RcLJ{fqMV5jM(`|1+=)Ih{{V1z|@!?lP=Y|hYS>mNA@qkRz&p(t1 zvbu{XXB16hp=v5~sZMEff0lSU&}#S=tr=sl1$E=)0^HOCpeM88JEvMF=K`f9D?sDi zueMSB`N$g+4+;%y&5;hV0_)0W@iC$zRpzePt=nd;7;HKvi8Ije3)-Y^3y_=c6Gvnq zP!5RT{H_?f>=MV8(+j2)qrBikDh{jY7Zjlp7#1NlbLSHQ49#Z%F*3Fi zWzuRz#W)u)wHS&B#@`W$YH=jOPMUx8yse;a5%LO1g#!&eXvD&N9YN&yWyJEX$HsPr zHn}W}QG*f_ANhiaB!V*N)eBLjYjhGfc}wly8p1YA-{pJJ;(6VpcR@vHS=J z{IH{|fBvtRfc4e1rxT~`@5bDZt_rPpVR6?{SCbFl?it*_gSRb9H4xzXNZ@Ro3u4QX zhs`3;gR5@vn@u0IW&6U|N@0EHY~anCGnY zUT`$z&G;5O%Ks*3yDzi-?xbsAXeMK!&M)~u^3qAaUL<^jfNsQz3Ki%$Q6WvvW5Q|b zw-eR`_OlWKt&YAa+W=8?8n^rLx_bBBttN)=0nphShv_<1cHJ^o)t7hTKxiv||KP7B z>Fsp|PbLB*Oe0j3gHUU-#ZGF0Nkn}P#E>r4 zm@jtV9xuasHcSch#geeE!hnq-UYVy^8y%Fuao{=d6xA)jo}~c$K@Vn0__U3O1Da?F zh_h~JkeZ8=r;S@1DJnI%^$s^I*6_Yq3^ocC$kQ9^7OHMj0r|uFEL@*TZBEr%w};}P zbAX;>A;Kl>8B3g$7aXi;)`#s5lEZR3Z37!_;`+V8y9E!wP4Rf&M?=d#r(v)JtX& zc}5hcvbrZTukC@5_KRa`7q25HbisJolVWCKLJ*!nR>bms8c9!C>Y} zrwL!0*)|J#rPjK9CC10l^-I8^GxwqB^o9Ut`dI|3`_U<93^pHQpco}ccD0EddfeuU zf-~lzfKkcmJav5bF2=g09Odc4H+v zZNDpjL-cQ-pAsKjMvFpIbVM-0BjPX(u~V^4-QyEJ?}ITtYoJ%kH#H3l-U;XaICBV; z{-tC?Ct^-4cl=xF)M8N+`|-M3qh@9FcvG)pB-p*Zy_G)C9dQ}fX{&Y*4W$5PRJq)w zd35Nu)7k!-7Jb(K7RW<1-n^s-mxK$cuT-H1`PO9#P-!>sXnwY6@-y*XB5V5&vKsd> zN!RmEKgFfnd1ZI}_gBC0J)V=QO&4~ufn#VPCTHdh?4%-pC*&@#bFQFee5Yp9^}Y?+v1YG-S15$CqEYa>cM z+8DYxm?zalC{TcCCN{zFS8Mh;s8V6c7^47WG$4}Mud}E{H6dI&;c4^220*#MjC{Vr zGRca5oNN9tJ4v?$*gdStDAqG$L;yiDa01bz`t7irLTl)uw7Z^8C}e2%Bj;Erwk8n} zUs@v+J|(IINI2~#;qc1Br=xZPp4WTX{)dyW^83dUX_j_aj8t?*v4)fsG8O-^wXDeBkLR4UHsHSW#YFBTt31-I$f?07Ote;ZfZ3m4oWa-@ zihp)P!L5H$Fr>82Q&V8IL;)0*>h|$Aa8{DYS27~r(&E5na!1P zCu2MOV!+SUzlJHuK8Wq$v@Pr!@o0LY<;kW&9f!g{@f<7O(Wuah1rrpi#~rJT2*j&^ zu&xZQ|9LC~9A^J7pF3_iC%UC=UQAZuqifqIe~RzVc;-D*o$fo0HOV%xED@Q6I2~`f zWI}r|nt<=ZrIX6mDqP|b6J|Ev#LS#Tdi%UTee2}`IlBx&9fZ|R>ksS%zU@}&b*Sz% zv9E^D4PH`!QN7Z~%Pmw*R|0jT_0IgK;EgUZ1^O3%hFB;0%hBSu&vZw(jt#BCdSpkx zDMA6K_41cEp2Mp3CzAOB%tah}Cf)@%l$JZ2eeAEM9XP+=6r|#}i5h)lsE41< z$6vjA_o#2=iQ*t(K_#zy-6z}s_K+~7~hvzEmN^XvVKf7v3KSpL{ z4R>HoClQI(5rg@#kL4iB3fPK;2{q+ z&48|@uUIXHX_#ka%VgyVyWg3PPe-ru3?u2LZZ*`rCK-WPNlY}^3|r%iVB{(4{Pp3? zX-RRImSyG6&BHH`CaVgBqW3Bi(KKeI7pRrTB%miEVD~5xAcZQWoCcpMcU99gNQ0;v zBD}R@&vZ7PeyMWjO+ir^z0z&jQRtOCkwJx7&;+(}hp0H22OtJ}n!NW$ue2jXmhGzm z!GMN5I+pFUoZ@!FjA$30HE>D}=SX8Yi_-TMOw7mw&>%QV+eu*UEmP&Aj@~<2y8Z1i zWa}j%Hb2J`gx6x6{HWXH`>hYu1cD%AF^0uDp2uvSR8rzN$UqM0FI0vh7M@l@mNN}V z=Li2);#9{PzMK*RsXHFUN<$PAjmsurktGeA1eHRF?U2&f3~tOr=f*`Z<3j9M(VRc! z4(ob2*kK~bM8$q}=5aZHjn9|Ih>C``g^~3cJG?U?&r?wct_x6XVz-T;Q!F&0QeD>t zf;JJc+g_URLa3(^*9#NxSRn@$hF|5fq$IMOYUx)NCTkng3M_+Y85f=E9JGf-T{BvN z4^%rKcdS%TK1+r(ELQJ{gh|r%6V3K3GRacU$+@h6QxV9Z)7^DJPg$6^0gCDcf~hs& zb7f>;LD!|Ky3pruH!upq%BO$gTe5{V?Js)$FxYJz(Wk|$X9_H6^wNl?%2Z$kpfE-^l)TppqD2e#Ly`#b*MfWV4Wo50us}M*q<89KQc^T)n~*@r#Id zhd$7sn3rn@(9xe>Nju0g;!VIKZVP=bq{$^m1$6BJuUjfEp5t=~%#Zl)>!XUXQ`z!0 zcvopewP&H<{+(B3-&0$fH%AA;T|*qFi0zT2p8kjYYLC4iKBxzK>4p#MW`rg76xCK{b?fIcI1Ty zelDo}lvB8k7o+$G;ZgkaVHH?B>&w!AsjLQtRynEAv>4U9D7Mh{t0{GH|FBnp4n)r$ ze}x^ezNY%d|L6TcY|y(v8^}PzQQ7|j^y zVR!l(+0#8V;06mzIDh#sggQ(RcB>!TVM-cFx}25o`0xAl=pB+{@Kt9Lm_oa6@bLW0 zpm~v0fPKJhHgXNZ&%J%b=*aMwTEjs17Gt35Z7*1D3RHKh??SXtFEBy9=x+4^K5=Cb zoJ&=G+|^e;68vTC0l={)^ zg2dSdKh>Rwu}!DzrF{OUZr(s1vIYmC5~ujdV!|*`QQTF505#?<_Mbk>p!bINWDUgN zfl}~{Iy|ibfPwynLKm6cj@2c1KaJA#zl*pkQwTje| zKsn5+u93!PojAS%T&m*13;svnSl-S0{3JHXcaz=|{lE5p9|gZv1ZW{XukE?u`fNyM zmi8Mm^@i_KlHOtvE^RD;rPXG={TsLao3qpiTy2L1|F!}D6A`_IZtInH@~dI7nY68}$|0_0HV(sGi#g&ylpfQa8Mk{Ac=2Tx5kcmhs6SaS{A!-g_nOI;9>jC~${Fg>~GI;2k zaH$QKE{gFAey)NCbu=@2r$8k1px$id&@NCSn|$x-EWN~}oQ!rP$qrM8%4xuHBwy$= z{9QenZp&3m$ zOw(FisX!!qL;Y_D+pY)dy#~mP5AxWU=Y0HPvQazrU%|dzB8smE%f7420``G$VF+4r3TFr_V#JZK4M1{MvufYUXW6SRQ~ zAcb8Zqbmbxroek|dALxO`UKp~c#W-13B;G%`!L6U&wxOBym%)|rhW;eKE@P}dM`EZQFD@V)ppz>ix0~`|lNl`HIvRMc5 zf0rW=TjKY*t2b~7EDZ>KPgLe^kZJVX0$j3N+%4Hi?1!JA(st5mG|j#F?t3x>UG8NM zSKF#L%tvx0zGGblVfJvoEapFF-fd8IdIKiG3Q*WCfRHJrU%BlV7PM9aBz48h%cGW3 zJK+t>D?#L=;P4~0`}(i8gh?XRG!%=xhc=wsYmK&?FY#c0%`(v`Z@Fwl8y<1=z5``? z7y^vYK7LhwB&r)muFmu~d9fnAR&&FxKIcdWx11eq(cvV-R1kZ72iGoo6UN>-o0@JG zA$G}l2>wlWb8s`9aZuj9O>UIj>*v1@qGpc$sJ;;TefHg+eao}uEK>|jOh>r z!k*Be&cPtxGWh<%I=DwR=K2Vn#`jCKi?xg1UjpO%AH^?E8G}d(VpM+w?rMphZ+DPN z5^pF)~pm;S8zo5VcG)Azho?g-U)^Fiv_>183n%)^|haMBrnn=8hWB&VXJzeT)hkZQ& zHeO$~@sZGwMio5?FcPSQo4TBk4)}&9Ue|Lo<2Wsd&c8+NF(}s4BMd_+m?9p%;KP4_hT;84svw@0^ZT20 zpY(H6-5qWWv^~GMcH0Fhw~DsUt}!<42Wr9#cvrpf@MOZI!tlu;VJ`Bd!KxZ9^_b0x z%8p&7ELtI$R~+yXABa@iUoHKV<+IKPbW%c#x^V3CTV{I&3n_%0?Q+L@`)**Mgx`5JQpqtfEZ5a&0r_3Wl< zis=vIv@9V_%Cwp|Y?KtBj1g|ZG0cGJ4yDe`I}nc8GqHR(;I&&+h9 z=cqXklYZzGDpjVS*CYVfy_)JYs!P8}?`!_uQup%-V*J~RbN!DiwLJ4+j#;exk_!;? z6(CF>s|WHZ9hK#IF`o%VHZM01EDKM(_bfMpfTPD=M4az7@KQ~m;bXBA^GZ*ck@YQ^ z`m8ar8C2z$O#Xc0tVJu1!gQA?MPintDFKtQ9+zMSfNx*8r#@1;bB)$#6-lNX@+Vc; z>|LKa1o*NSWVg2#+1u~Dy~KYx_P#PdHK2*@A$MI(2g!f>0S)wYwxIzxt<`oJ z{R*idC*j%7)T8p^8QX0ur0+hsDsah>&`f(IxTFaW^T+-oLGl=lXYqJ^uqRr+{N$J9 zR1>%cj}+z%i9cQux(DiOQ{}`FdP*9$%(!`O3L+M z)b#-_5pAM~>vA_B`?hav>PwY#b;5rZ7{&lL}C_v|Sp5Ls9GOEAs8@CkvhTf$u8mQv(F%<$kk|yMT4r zm?7F4&1c=K01iyH+cMnfA3e3g^DQH7>0?lCJyt={ZGTFb;us6Vaih z!$@KD6vZ2trCz%OHRerK?OauFQk0!L70<1p4PvlR)wWEJ)Ka80E}kdd1xJ8-P#Rie z?&E%6rcrI`e*o!_F@B7HF#NY2fLw$#N3hBG7p?sU-Ch9QE>!8b6g3)8% zQuGm*Ves~G@nn9mXCBZaz(v=`w`=1zTHS?%$x&gGRv~_C!v!vX@gX0{ZPpcVVN9d+ zUF%Q`L&THVZl^_kxo^^RChx|-h3O+|ZlfJCFYill^Z<&i0BE=C82}94M5aFGDpb53y$kA-UVyRm=#y235)MU? zPjLB3w9{1!3Xd61`6mC~sk0%y+C@0} zcgGeX;t+1OcUP@<>j`4JLd_s^e6yB~hZNP_;Dh;5)NM6qCTorRld__*%s_~5WpJyi zu`o-L@)Tzm&$NTX=fl?(?*Ql0o0qQLg+B)Kpe58qQoT3t3(6!R9zvnCYtdbP~0 zwQEyY#Hl!|=hJ(D@BAha zc5_}XxN^&GrZH5s(3Wdle)_|V+hA--bY=B`BF&C^qm%HtH`uI3F?Bh!;L5%lB%WWW zl6L?0_w3h%VQ;=Fj0*aF33}#qeLa+eYV!*b9yas*k1%g&#AasIX1YdPEhcy`cYVN- z?E8H%P33HiB&&l3=m1l%Cf%_MjQoH96=US4TGlW-ou ze>}J;T7(^%WTKec!nq$Z$rieg53_9+ol_fnWtl}2VhA-ey2z(PME7rtXLpstw+I{qBhU(R7W-7je5^&_mso@n_uGLT-PmUYx0gPMd_Krep6 z=QUr$mwA^r1BAca(+4J=$-us{MfUTy04JkqwB3YWDuPds)Xq8RGBq$_ctI`3T0GOT zvn-XDcX{+hgVh59$gfOem)%yiaie;&Wo_!_73AXnW7!{A1hm?WcRp%@%j^u;#8u)9 zMe1*Fn#A~~@0Nuj4#~WM<92lRmgM<%h#8b{_gDQroUaA0Ij^*s)`m?(Pm$IE$aT@3 zrDuz}6VXDN0a4nh?tYrwKDPz3c9BAij(ggYp#VzGGsJsBOulO@4+_izywjCMYg6!= zG>-^{W;9~42Ttgv?q)bX4qy`rxtU2Tpalp2P=VK6MW?D&ep8jN3ugn9VpE5YPM5M? zY=*e|5Q{JFNQ0;Ls}`+Scls^tStWnE_D6F@I|Gwjhan$PB zR*Rm~-TXDVJdXZ1mxu3Kl7I_eV!_x+3lDkmdF;zskFGdrGHZV{LMchqL{j(*o)0_W zxD|V-MwV+53e+A1GKt`CV^6J63N2z8j(ys2G8-u7*El_F;oFR`rbyTF6{0-Vo_P+p zZ$7>FbkxgU;KI?q_Pc7ak>{mF=GVW)oQkd_mR*Wuanye&VWPSkoL&8*;=oyua#1PM ztIpDBn8E5D)6?`Fb62_s5)|5ybq<`W$-swG!p2@6(;gZ-IQbad$t|r}6(>T#MiYaro=(X&-MR{(%13U^NWZ5e4hRhqvHA-!ysN%v-w+DVB zW7%bdJ%ye7H592Y9hC(Ht_bQo#<6Y_wFe^`poNv5H^A#bdnTXgFqY7FJTM@uMx03Y0!i9c%y68Q=B@=bdz(UK!u}X|Nfpk%WgqScUbq z6IWm>E{;YCtjd+N>ONsNIy2eg`_Bf?>-oZx(h#3BT*AMZ6E8|1IOhdgOs9$q*+~Ga zQWM$zf{n+nKZT1ft{X2b-xPw}3tX@1Mbjt_pkaoIQp{(7@9BYy?BLV&#KE~A0*tXg zLCy47QeUJfHKVk)KZbZ^D}(ppX$MBo=xGS%^IPDagK_L<9s_T1$@!RGk-08YQeEKN zFWeSw>nmd|(s;;eZF;Bs9{Cm#-;3}Y9{avXZyXj0_YS>vD-=N)4TWD{{^kvM#n2Eb z4IZTy!$&{;x2Llz66v&m7m}bR-gA7BD+zOSviCV6J`1Or+Tl;X!&EqaaX9Uq0vMRJ z2$|?*56abQnKj{USJx1Iuk)JEom=~Ybju=PZ@9mXi-t94TQa|XGG|Ne(0hnJVaV2r z+f&Gvd44pa#S;i|4HQ*g!klUjIAIzV+|mc-)W}2!2A$^Pk25pcxR(Hb7UR&0M3B46 zW`RdP+wDrr&!GA>u*T)8l1BY;Fk8~J;>KsAH?NB>H0xZk^!Nwx3$+dek)9m&aX_C86p7Xb=%_Oi9B;)X`83^42HDMri+TBt{KJYsbZ%p!b@atJVld z=&__0yg^Yb{-Hgm<~6}@wacT$RL-jzHw?IR0ho_P`r74oa%t`VZ9!4YcSAlu|r zuIe3zkF?_K%qa)BLSO&OHIi;`^!NrlBIyHjPKCZGiHy7oF6O01VvnYxZrnD50#i#h zGEuBLkwoA|^zW`w9doLd%r)Wu#WaNMvG`k|kd1F}WTu{y`XtkI((KP%@=@XKsb6k= zdw=GVJrw*e7N*ClTnj;($| ztxPRTr;)_ew0%uMU8s?H>VO7@6V6Wq{6lMNTqEzT@R1|;Yzhs&P*<&o=JpJWc!}R> zx`ErXYs;iexlu@C(|fg?uhMtS#IZ%yTQTf2V0iO^d0ixFa(Dn^PJ}Vm5k2BMN9&72 z?BESk+vI@%#oAlOMfHCDzks6-h%f`vAwxF`lA^%SA>AM$p@b-i3aAX=pme8nNK3ag zC>;_?Dk6xWNJt1GoHgFR`~2^7{{IK(!Flw3`5pGm-q+syx~{d>`}0|2GsOPUw>T!? z?UQ+!OcC~$7M-MxRq+Wrmx8;*g%VJk@*igc-rQv6+TA1zTBpihW27@BMPC2iZ*8|G z_dx1U%!1th81{8nUhQlQ?;x2k>*98j$rm=gzEG_|t-KFBjRH;1W%*cSp!e;hza0K1 z@IXtEZnT8$B_TDBpV=Old+m9Ce)Y?lnUe}zFf}k?IH}Sbyfy2jhkJ2LZpib`K=H0V z^5x74U~Soz+P=ox$g~Ehda>5TWCV>te(&zD zeteS28tBk->AZwUmGFKaD8qs-UA{SBfBaR;gl<~5?5%?BqaR$;Ukl2G+&r1%hbWaJ zQQiEcQS!z}uN^Z6l@Mp1-5^F^Us)m840e^8=5S zdDqcSjH74&mNVgR4)#D{Dr(%c8uX1q*<2gGs15f=^zoC0m&!k^MVwUX1mSG?F$k=s z_yfo&*(<&&jtKgxo4fSCe_>yZ`#fQHFL0@<`kKN!7PsnDM7FZuowm=_A)Uw@OdcWsvl^f3{80GPF6hPLpn`$xgY>yaR)eb@=HGEd zEB}w<{wEv!@3;rx^Z|)XzWAC%RX6H#@91v-I6@=>={O3GpxZrsBt84?U}5FqBk0&% zn*WBNLWAHu-0b@#vjvIbGxBK2OMTd_>`7n04_0$2TmS2h9#!&j{7PtJAo`%%#GEidQ9$hUl-}E z9J3T9A4JM#TmYp>4_M}(PinmQ`m7CV6ibi?z3CdoWGd~U4Fw8>RgB!xW@N>k&3s&j zZ&8!AnB%}k$*XhN^elS?PL$RE8yo-1U%BzXNWXvMBWR-J>yd1J zKC|`ipc~5Q0gV_TTk}~o>iszsFPMIT37I_9^O;wss(4Q1NK3>}wZ*M~BgYc(`oTg3 zkRPWG8?!4J3!tJ}i?Z!hW7|Vc%8qzMQdlrQBq1o^Q$c0E)x#0lRa*EzvysCyj=yH- zx4efptK?zQ6(NPAno1HKqUGt41b+j<2C^v#Odh=GwYIvRF}c+%c$a;8w0?!pqPB#` z;YHx2tRyd9wi`E00;PZ^PMcryzbdT~lu2wcSVuo<$kJl-Tq2d`uN}O`qoO@@(oGOUQ9|EAl>NCJP z=@yDbJ<9^4n=Gde5ZW1e_aV9LFR$n^0`3O=8OMh=8&->o7b$VS73XXJ4JXMutFanj z5{ht1jt0WRT>et%$!e!qt)vSIOUy5%@8wnB`D8V8^^dFc_mZkyvnoe@T=gxz;gm-k z^9oP_i+BtLrmZ)0*8dDX0OCEjcxv@s&U3>;{Wrg4=4fyIn#}|aTl_M>9rl4R;z9za zD)p(54F2%9$ldi961QJWw^Fz(_eep-gpgkRpV>vVt>Ck`P&yIe1K*ieT;RK3Sn?zcEe&cgzpTN1D&VRRR=VRVq zPSiaT3CilE9GhQI!?dI-_jUvE48Cs+{#8jB@&uMMW>9{WpM?7f-`es1Q8kbP^T1C~ zUdsMQn4tb0<32#xZ@wUm-#G4UmOJ1o{^)<7oO~}-5(JmXLii!izGZRvXp_T+Fzg}L z$5qOlC;`GJrsApL7-A~56u-fHP%pea&=ds+5q_td?T0N39Q2vz-$7(J+$i=xr873- zGaw|RE%$=8_dlh|CZsM7`KDNIijk_E-S5dW;nzPzlOg}uSPHH*TdT!oj!mageXwIJ zBWIO0T?JLF4Yh>VV*;u{c%#7X?{($Q(Vz9i=^7V-%hW984-d9ij2#+_q}pOfo`DXi z2daxCCGke^y!a6XqPmGm7cUS8kux8h3_G@~Qew)A!67qDu)K0|)(3m*BEV_pq53|% z_vOXFt@)_ovjNo8$^!GAsFw~+<>W0BkUIC0B8bpWz}Jl&!Ez8Y$D|AN*lg1 zPF2{cVk1W&qng#nBgk0x?&UEm5bN$%VFwcA)C-MVS zk{$}l2g}?(Yr!2uQ&5EBEuc$L?YL(Ib-aDBZ8V&L6ixQ(rJ2+pK3+9iuLm2iJqV`H zdOUYT@WE>1i2K%vqU3m?LK4j*k2$w5Y=1(H?Fk96Qt^R;dPdsLLp6&|*k;%$!ho2g&{k`s;g83N^p0 z4Y+YU>gl)954%ty4dx1B8V^*Q`I2XKox4wAs+<^$*!eQD^Z8To54Y)RCxs_~UkjGg z$aPm|(mwHdQSLfbSu{(?h^1;>6o0V!hK{Fc$Q7q~&^#yr4?h)%3K#03IIfGR=D|J^ z(Hh39fcYPVkXN;;18B#$Kn+f(WlJL=o)@SBhA)vQ3*HYa*DnS}@d@93b#;Iqb6clq zl2fRkrcB+#Oof0Qr*B1A| zJqcdr--_T@c)nCH9>K0o#LB+b>jj`L)hRw6D%NB&j1UpgSpx^3BHkjbTDN6#`?rmN zgUeTjvfCr@KbxsB5t>)nYlyS(SOU>645o;KGJoAA!o zzS4)KZ8nE51eM)3a-Tfu4J>T-8Gb7(7r%tgnkTI6xPAZZ4YNW!H2^m0(k`F@MJCDT zVY$b?<4(8<7sK3C&L)qsCl1a355+)4+7$}opQeM@R~Y|PZkQMQopfDgVR9oTPFX(n zFk`t5CLkoJQcjx}Fk!#I6iD)4^AuT$g(({TP6px1dTS+a*abdX0F4J>!D~Ib8LGx+ zO!%b2S&9izg(#c^;rjx0r<1%fa1@I0nZjhJ3>?(~0V?6BqodqF!l=S0(q}`$p_s|b z_HTAu`2XP?aDT{tXIrWQ84qulo@Z~*1(mY zR9*pN{Q%~#A6}cTu)d?vlQk}hHj?|GOjZY2&K}S{{X%`NUJ%IOPMoGFI8Fq;ixTbF zIr!spcn`@eB1c$Z+7=)oI8lT#ifaIRYjXE`FcsJ0*OWU6VBR!RB$%!Rr~U|j#-nU_ z>IPL14Y5}sAO`Hn8g2FRsD6dMs$kOZ+%K=p6;Bf05UIXew1HsJJ2SU~%j?lfg74MGGjvYdJ^0!XK~ zv3%BA7@ZV}YghLdsrPZ<@Db1-?;Fy40H4i3L zIQIc|GNo7gA4JQOljaIIk2VWGLr&!iQnm4yLxx2IZuNvGz3~(8`#(P6bZLy5y!6UK z43}&s81i~ym&paLdP;&O$-u+N*qhRmM)_GIL}|p5t=3Imo4UE7yr7zIbT~{Xiju@M z%Th4Qa`q>b#VX>SQ}h?+8~(B+Z#PDGSU;S*A0U-oT-w;D`K!u`HcgG99_hiJca<--lfBaR%Y)>DmB+oqGaSn`ci6>Un0ZuL zmYl?k$_b7FG$xi=#_?AG^Z95J^^ywgu>MPKjSDyMJ{$GJ3BoqBj&^4QG$Cx$_!`(m zd*#t?98hL?jrdj`|1hMNkX4hgNY2~Mg-Pl*eXkOvB9RAB4zhRd9Hl?mT6-whTg~vP zKVfht_gep_zVpLwf&hPPH3^>!l2tCr0{{zcd9A`!|5Y zOe(~ESzi10CNfxy#4Brl(D?ZCiUx9Nc|E@B#fL<<>n}84hJ1XKIZ(^?-U(Dg(R7Mt z)L77J>-N4Ns76}fBKyw<5z+xCMdIPCPa1L*2jedLXDVsv?sPS`PPTB6+Q^icR@`Xu z4$z%}*8Q!eus1QSH(Ns}15kbaGaRakLR?plW>sE@7jggy@vG+1JcA5K6La%> zE7|cESe{+`e4(a;gB5Y1CivPh*w{uM4LAw}(DEpJNW4~CGJ_-8h!HWXR00v|6>EVR zT;uJ!$G>|Y?|XMXFpA{EZyd+E9IKSpH#HkxDb4zy2?Jn-6hw)WX|)rRUY`}qwGUos*`**Uu&8zA11nKG&cyeph4E1@ zJwX4$pL{OT3oSqT3hZ$TT?=K^+7jgddDYe}z4_ItOw>y?EcJz)5J4_$E)FKJUKOnL z{UYK0Xv?y9_>;+oK)x!nmDjp7Y<4`qc)ZALB5`Ru@4Bh^rxG)q*gj~*Xc}@u{m)>! zPMrngqUqY(Or?5SE~5XpVuV2;?qct(0Gl8?r{IIdkH{e3&|%wL9o z?ps`ti`~vPy@%rl8*v??gZpZSW28ldtjHro`9u1StKh7@{u&*MGvzt|Sk{`NQ{0}p z7mu>qGO>QAH{|M5v|gJPKp;E=Rh69XRJH|1T?_QzW)#?r1NO!swL(PjpSkTDUwNf+ z|DNJgcTgm`&9j#U(IN15_fLLkiNno#Kf>*Nx5pxRSnp|>G5F|+fUA7&I=(`Zfh7Mk zO-Ntqj>P(_9E!_a1^(l=72Jk@HP@N?ivax8ViWF=WlP5dreX*ogH)M;yMCu@8mK#1-YvHykp2m-+QYmC*s z5-0d?&6rwyA(fQvmEH_(Y`eOd1#Cjx{ICa*!sSPuCS`N%cXVC|{h?&m&_sgbRqNo> z22Ty23rZD=!Ha-48}5^I`c5|0LG1f61yerkC?D8n`6B8hi5@kbUX|pT>o2N|(m_Y+ ztm^%vd1=}IZx;|t`^Ltv=GY@fG6S3qyzv{ZZn|a9EblFOx2!2Tine`po-8~H6=~U^ z4(D;0A$+y00_!@~^^{?gdinieq>_;#nAAmJ!MI4$+v_PnGt1Uo>>l4XY?JHed6M@B zDJ$HCv+a}~+AA}34 zukO6vy4lo)AY}V`g6q70Ia;IF<{rxDJ*hFhT@>Ov8pr}aQVNqs{d8Q-qq+qBMnh8T zHPz1qyWTz_lYDKKPv14_NK*D-y=siR_e~~+I9}1zqp{GPn$q1xN1Jl!5|f2xTjvL9|~kL!yCYXAC>XZ5xH`L?LnH(&|Re2@UvX1H~WncDS9A?pECLAlat z&K~Zx)p9hpM|AGnL!Q1ja~7KMb^^KlGC7}cpwtUsS)~)gnaAl#`&zmFg6D9nisy!Y z?Vw+XdhApfCt^XEcH!eyiXUBw^888g<0ukU|8rmd_o2&Cr0ByVvR<)WYJrlgU=in0 zPHFah_nM(E#&u+M*c_=@>Q4M5{uSXBScPB)~kF1DQ{=p@g58Pck*rq`h3oENOp-%;vgZqK!XBSMv5C_~q$Qb@m}0=#UnV=b z=T-E#<*(|54bV7jBvC22zu%r(QlD;kZzcCuE3Qu#c8Lg)2dz{me@<2DI1XOtK6BKp zLBXk>o)nb$3Wa5WB`3CO=2D#Sa@vZE8)lXxDE|PO3}B}wB-Vw$ImWQkX`W33gS#Mb?29qhxZ!6E4Ym9Lpy#m`Y zmqha`wGY?J_SEiuQac{1{x|X;C@c7;9Od`leN*~)4tY+tUdwhH__d<5#F!+4Z*>>Y z(XjqQdj&nm!K90d=C!Vc3q;iq)iWYJbh#^gfu}VBvWX2PB}L_pXB&c5?&T^0BAhsJ zE}i}Fy+PvpN05~OdVZK>W@BSyCu!$TyYQIkz3b$QK7YhmlI= zw~_SQ3GtOw{9?%PmA%wUkW)$Pf71N+YqK(D(Z!@I=WYt|(*4jHDgPe7Aazf9-p?ag z#4+x3ARPjyi2S^a5+BRgF)5ve0Ekx0!0FBqL_t3IM7Tzm&CBeF7K^?dd$KG@`0z!a%ra>3 zaM-D1;IQ`zyxYuI8I@r5=&7eg$2XdV{^Oo#6&$P8r>W0;>tHGo4LFGvXguc&^(N(9 z|Gr(@db6!u`QUFY-a+vPxXtTsJy?%^W${q$<4=xzXOgi6nSPzw2)zcl9{b*7vTXb8 zZ*kKTx!oBS{pvMEdFQlOF8LDT9N)h_(1k#Cv|;vx%fC6k<$qi zxUCO@ouWerc|(R8CXK&oF@EW4ihdMU1C`c8>jbav~s3;FQRUzab%-#hkdWPVb;$GS|AhHQ;$ ziUfMRKAW;(sBDIo~*^&hE&A`^iH_aR&78D=>t<5qZ4ipqHxf2t4)tdLU@6<2c8&+fWb9-xZ zBH$8IY4=COxv#h!#}SVj{lNa9Kx=ALzsR1H&$wg~Esf_l66C=(m!w@PFd6$bi#1gT zMaG9Bni|{7a0e?;*m?}X^KgRF3u(8C82|y=lXa=5QG-jr4*XMjfd)i%DDvu+SJJhQ zPWR*8gG|}AI#=p*0og8+|C#yp#i zh%-hyRj~y?Zi4HjW_;WNSBN^ugvR4c$GG!*-ptLYEopo#4Y6qUsX55BtZ|Ol6m3sS zxQ9hjo5~^}rQ;fS_rQ)rMGC z{JgxhO#Q^|{dx*(7YHZ*O!RS<_~J&3leV3?yh3a;#v-)N-(4YBgx!Poe$!iP62Jjz zyR_O_B3qQoYYk8@e|d;#A*J8&%`OK`1?2xI%um zc;+p&T-cifs^y8g={ZYd9?E5>^esZm;hUw(0m zi}QfW$`JWzJ8d^_)hIscXhQC(O-E~mK2<37hGbqUuySX>BsAl|=1q~-ZOWk!#WH{U z&L%h?+6jK1T7PS|nio00v%j}6u{E{5&LxK{JBY2jtn=VFM&!@ljL_3M8tgH(l5#vf zf3O^vWNgYHyi^bV~yQHKu{GFLg97nIIqLmLBi2=yJd7JH3Jmqs^{IIhO->gQTzW&iv@rBKccZZVGrRxSandz?jj5c>y@;%e{#*YX$GolC51ZdI( zn9f*`7Rp^BIL}_Ck^>zu7xQL`EVLdnVmxz5?m+02BkDSN0kV!EMW2!bNS0R%ZBldS z80vdJ#P?pYn#BDsGp)$pdVfx6b+E7KTFS$|nb?+SqhiS-wr@>`SNK_Z(>ShU4B3K0 zXyapEY83EQ#p;v_KPg=iobWX;(-)Mwcbi{!u&3Q~UfyTz-gP}jp6RAKc4#nBJsEFe zRXAJYrMt>B;e9XpxcjV=u*HK?eveYJQO&YJ@4GksZre)Ys?1vW@HWq-Z@OKbA9$`J zVHd0~G^S-2*4Tn@Te6f6_-fhY<-P*OrhOUX;HdsREjRWJ(kYTJk1g#Y)~9IHTja%F z%F5JTGREcc5C%2t$+&x!mq?Ra{M-Sr{rOrHcXTNKoUcA9`Teyry7Z@cl4?u|0|NLA zx>~By!;x`ZHuAhTq;8F}PY?60MdM(aK?IPVIk_!1#(es#*x8RgkRr^X5UKrWSC%aaGkT&MYn&9#$F)nSHX(Q@uI#{Z9@&gJjM-~7IJTs7U$ zi_t>H^BJgkE1)DD$%w@=S*)V9@VZH|*rDH<_ESS?#6vy~cA^-BRnpMt`4>JfN~-+R*>)pj@21Ropn%=&SPvJri%m@BKngzX>F5=s?NL)M~j{e z`jut(_5xeb1-<>eGp4w-1zFh(t~cLUK{D4bfvZCN{Y?lDJbkgmD8Lz?(H|phQeXWU;lWvpX?!W&m6Lq^vfOTi?DE zD=n1Z>X4Is%kU1<37u#P@ex{X^ZlhmGto#?Ut65j-p{%Ca0LY6;(SXO6)#^bro>b^ zuF)p{Dmy=Z-Ye8K!V`KZ3}npZRcw)@8GiSo5nMB}jB=7Q2@jMeOFJsw^Vy;fqVG zGf5~j<;i%`An$8hE3x!|sd23qTc8wtW3>KruZO}i?P#X2ko3VfeP_}u5j#w^>YEG7 zFZJJSr3bTrMU(lXDx3Al`fa0cg$(v@-R>tF+t*8HRLpSMB*kHz^RB8@hfOvp6fv}B zw-#aW}%H~7(W%MMxRvAV(U1EW2>S6qff3w2AY4@(uU@tI{O ziBj~hK3ralZa6jZW z)=xxI>VCusrwzs7a{3cA&L@1)a7>8sgYFE;ZI<_Rcy313><4&W)*uu3belm>N@Nw% ze)W0JJG3fICr=gnSYHr(Ln2Fx()0soGK1r3?3{Bw%)30#^VdU7dSqHoVU=oL3f6XAI;J2XaPH|ruug5_o|Le>qD84@`&R*dF7VxpmT=!6S6h$U6wInUUptC%&p%$)zJqC@CxsrD2^=qZgja8Qp*3?fDu~kdl z{s_Y>W9>L>#{Xycd{nrYrwl;76vhN+F|Aaqef7)s+2x20aVXE@$1$ zJ76A;-ODR3ZvC0OpI6jaq(SpS)PW3yVuS8eg=AV^n`wT_VhaP_{2fzeOFkRla_LUl zg?^>fZ}b%v`c1N<0+Eb4A}^-i&6k_u7d4dQapX$(KYsj}^i7jIiaYabaPD zkvrRPq%H0em$UnDJO{c!2DRLMlP0^*w07{BNXV+zU*gWb!uFecue~Y)va3~ksZ3-j zE=559$1a{qkMEN)-ghpdN8L|~kMSj+eVM$v@LSf>4ze9|y*uNk7X(h~Up$}OZn7Jm zC@xu|#2b=;;Z|sz>;1VpR-nfb?Ng@*9UDu5b*=Tp z^d<7VmKqFvW^S+6QSbVOd%D4;^{zY16(3w`rDH=_UjiR?Fy(z_A5B?!Lp?k!s*iA2 zwOm>b&p&DL5%}w)Z`{aZOWfGJbj@(>+33Z6ZEcD@BxHosBoxj5M= zz?*!Q#_F7xqaNn8UNX=6w^o$Ac_3t`L+D z{6{(TG_PgK*n}C5E>W^vc@Wcb=zRIrUuUK?S??Ea1^OYY6NS8$*e_J|?RS}d`|Dmi z?e`5<-&{X$_Qm1p%R;L(vhiF!n!e;Ok#>jLlBjMl<_;wplBu=-XrYDov{V@M)NoXE z%9APna)HE_htxJBqjLsxX(8(JPiVG@JIC;P?$+J#cK&LYJq5H#Zmry`!+wElVTb4a ztfn}QKj*t=K7X9X&C^9ESJ<@AR+wgTsA>mUDiycRa?jeRcq6l0N*`ZreDx;Wutd#Q zGLOT)gX9RHnUIC<|I;aukl1pau}w=nW5E{34#+c32aO3!-TG{-Tuu_qkEV4#`e#&cC(zC zDku|-iY*n6dmfP?rJf?OmYXK`Bma}H7>_Or@AtirMl-~2hfUW_B9-=aAjfLbEC~x#uM4S{>3`XrA#Ur?mM!J6sD>qF zPy4TNlqt*QZX}GOUh>2Sy?K9(Ig5O zI)!(!4^!ljHn=waYA`!7p^@7B?({->`HYO`MoX%^OdC7QLaK_A zK=GcHu2?ssw1G#V!BI>CDAD9z*Mg{PY5B37B#p7;b32+;ZY{H12$X}}B9>qoQyj0vMDZha}za`5re zT^TgG<6gtQT=Cd#A!iv%KZOMVbJYmu0K>Sef5P~UiWU#Nw8^6e9`&Qy@sCMB*LDIB zuYS_MX3tcR%vXE}<`3LkE_dw^CG43@D zBed~>`;l$nu2TSSIQvb6qzW4Y!V`18@mn z>*QWxp^Zc?4W^{|+;0t!Ql4Jhg)H0{Fc+8-1qJ7H>MY_Dr$)e+Tm>vxNvX6;iccbd zMl@#7Y{Na2TQcYaL8$~^q}W4dXM>W4JCLkTcAW$471 z4Xk{o?Gum@7&nLs<0d8ZBLAET1$=@nSAAr_MU$89soo%+ZAw1qEmI(sTNT}jwzI& zw$4Ct=u`7lg}n}nUcxm=EoZ1gA-#oS>((=rLNJ~9kic0%;!jWrpuM?q6 zsR+J8D8U$==!TZ}5tKv^>05lE%&8=Hb0`-q3Z<`}Iuj;L;ud?ZZb|jwlGj&xqW!?q zrY#LDQH90Y_MMwffAh}YT5DwS{PC?UyX!580=4TTTKpNui`7glqu=0OWd&Lyo`F@R z$c6oY1^>@X=oqs0Yp33mf6(~#bx`>uF}HH*&$&4K(?hm9ZvmYTbfLCB@qRR3ox z5pi8lh=qsuMFwIT;;1b6^tCgC%vOI{we#Tdt-pC`+22<0JA~>Me-$sZA+GP5wV;&! zgWF$9Y>Q=MTfB@8phDs@eW76pST`zH!-6H_dszRdxI4xG%cdH^Ot2FM19>zEKci3N z7+_;BTPUWaiasU~{ zpVUrQ#iQ?rG)ZysbZE94)cF%(k-D!~hwUXJ-e+8Sm=58CVykt%{8B${R=>!wt78B5 z>-nHVg7sTb?`iQ1(^8sUlAkk&r>bs_ohEvp6RKu|%IC5(ue@ZA6vkd`0r!b_V0F$N zGVDEv1L8>uHg7LUskuRC71@oHijXhj_}+Le$SPfXOJ;^J;!A+BCh5=HM}gC zEIpib@hQRS<%PIQ!b>+TykL9Wdq&RJza3~geoIXdKx=Aee|I}Xho7I3huu!&1)Gk0 zNLrF|B|j9HJ3NIbULEaMqN!-J2Ua|aK*gU!@bVfhuFXSxCArTvpKY8jf8+X=WBzo} z!Ph)66S7_`1-QGPJ1oBpey(wJKf*+@_NuS1A2|(ih>_qheox3G8MG6w{GNZx9??_w z>~{v}8-l5A?>@(@xKCOD$#)C5;EsDYUREggkZ1&*?MsmqfrPo9QucXi52ZsUE@f1j z@9z!UVY|Rg34N+eHUd*$c>VPQTE~vW3nT{|sK_6<3#6mCHPg;& zBk04X2iXYA=cGKL1ks55xfUoVu}3lGcVv(F9_`=czus6Kv{Eyjgfx>U%kR>au!pWs z+Z&yf-BjX)MxNsUQ)8vcQrUmyU~~+?*h{%d7hFyL>iT!vBbZg&)O?Z<(i9iZY~xV= zun`MQRfH;C{uw%9U0^1aKh^?xC9{PNPdwUM>R0~Q0?Vc8qfkN@_lxG(q;=Y{|WsxUs#NJIghV zX826n7AlkozRL=ztMZEiKRb}$p8I7a&+aHb6~BR?_g6y3L5|Y&>5EHFG3Ru(@G$|n z?~$SRIk6)yuxn=58tCc1nZ7Qt+=3L3>3;O z!8l!s+ZEnQUGxZ7>?7SxJ6tn^KQEhKc7@lc!SpK@sa;iLNysVrYbGC(Qu{!>GE7(;0;Q#nTyM|Chgp`>N+^DI9ex;sMo{iKP zEz*5{f_W5LB#uLsf~jgzILr@+{Fc-^CwIxq9*(@gzOh=2D;tG=&wX!pG_ulJ+ws}D#(A(`gxSuo+C;U=7%P(Z;yJ(G}V}|l^i1~4@b$< zpJT@twm%GERwQ`CUo?P`_loozN}g?2eX44YpojGdl|fkeso1sS&)Txv+eMxXMqU^XcIGw1FcVcx*h@mV=jHIkLEe^v;9rh1Ftl#-ECequqC zj;`78no*Ms)L$e~z_JDHSw!JB9Ii7Er=jJ8(OoC9{1I8RL1W>;QD>E&9@vyxHN)yK z9t`}Ov)y~bkDT_;{CMXm^9>BcX9XK@x(z@Wm6%3zYbDK3cfo!0lPI8cG`ynHgtD~P zE7f+j>um^)L?U*4f1yQLU!ak)Bt2ATsm4Ji0@7o@;$ODxIQtVH+2oQ4Y?xlC13;z{ zjzib!iQ)Fxz^FY$o0i)U*WCG(t`f<54fa*;4=={b6?}CW2n|@$wPN6!lAdbghte+dSlX%8d%yU6*?N`vRu?JcFG1_aKJx``HSxmwqhJT0U(2mxB#oF0jsx_Y{t-7#;gYTxM8dBZz^`9$ zko^IKwctV^OglGEocy_flO!=!T%7O%0Se!pk4;#XLna}kj7DpvTR?7(gD)YYoUbf3 zrd5(Yav13q)J9l6A#A7Pgybs~Ys5h5MGKqf{z%(}VYy@3CmZdjt36lrEu`-9;LsO1 zuqrO6g5JS&5}2)~bgCcEDGfqL+SYD9tkd795B*|vg*52BN|0IUFeeOwxw4>BVZ87k)( zsE0t=`#m1>6~2 z_~&nNT*IGOdUM1`c2Ryy`_Scj!RrusU0WSBvgS#4`x8y&D2!G!ESHA$cWndIV=T&1 zYQyXZ(Q+WD6^IP$A|8)eKG~UY^2GsqkrYUJ97(s^6-+%AMVa$REy6$h`RL1&F@DY? zY!~4%ds#>k^$7^r&7GT^WTWi3+}-fyQi6?TIdgm9ODi$pOB4n&&%f1o2w?M{oIm$+ zT;YDFdLl;V0XkK^}~fJ$ex(ZA{$g)fD^8Vd>{bG~drgq5FD z{d%#@8uonxx;(NC*psf_3$kK)+G)<#x*=EKbtJl=rSuI_`M3q!$g)j%`ljTczWyEP z2kj%ON7{_?%x~mII2vP|!gZ~GZd%$EiL3R+*=fJH6bwBv*n-YdJ)~d|#lMYUVX9Iq zl!2zmvMT@DjfARVt<}x%Hdo6gn?22yHR5raBSFXDmCQXr8Kx-GydA?P&UQZd2Hr3+ zC;ErFv?$J3BmM+AS3~qcFFnRIkMrnviltobsr~z>H|u@b{kC-26kvMI|J?cfPa#I~1BwR=TqR{(kS+?ZYVbg(z0T3`13cyubE}IXDO<$avSKx1N)a z$sx!M6`vcgvRWJ?E6r^`k6TySON~(KxrL6o=l8QGKD&|kX~hXM zO_erQ5@a_KX@CIp`K!K?wa6(`kY-@yFF;lTT>xD=WSN5Q(#fGNP+`=qa^IW~FdKg zxVxIkXw3F=Es^VXBP$@i%!PtJFKwG}#q%0++DlzFZ|?owuPF1F0Q)4G4J(m^+viD*p*JzN4{IMSDn9k0{R;n_?1QH-U*1%4Kv7}q&)C9m-`y8aMWelnMM#$sxb9%;SuOP)_DMDNZx zmtWd8Tt1Vwlq!!6zo?odVCndSb?n&J?rdi$5iABSOvdchxMN?vfD`UuSyx@|PY%n~ zf9B7CK*FDVr!i(n@WQIB7~~+|q}v{F@^)tDe^0TVIMucv^NOyK8eDW z9(@#aP|e1dI9qq+u%Av2i|=fWwl(J#cw_3=YrN!-Os!RlB{g_8cnG8f>`w= zm77rPhfLzm_9wVt(Uf{Bf9|K`&8QoEVSe`!qcFWJzBI!cFCGM>6hZgR3avFMR}5*4 z)(z)`C?hWOdMj>TBb}0t7kEc4-0zT2z07v?R_QHW>jtkvdz5+(T7s`L#Ge+6>4eUk z2JBY65DH2}!8ORQB9)eWHCgx)+K{HIZGtLlSDKS}F~#rr@ng|Fm}hwjl^1Dm8*7df z7^iv_%8ye?@T0MeqD?d>W6Jv!}*=s3Pig`M-2k#-4T zOTeqL)*fbxS)>QSOyb#U*l9*FlIXquq^}tINQ~q?>cYM7!l{)nT#A7%THKOGE>uPK z+*Yr!VSN4TxOtzIQBf*P6~2rgt?xq9N75r2T~afZ-y9Mg#WK$R{ zDmhttDJAj(dW+bTRdgGfgvK}(D%9SquOA3_X|zX6l8lxhPJHpAO|6&@+rz<_`#H3&!7mnvPAu2E^6rQ{c^%bOU_^9FhA zsl1IK_HCO`O-R*;TYb*sm2L(;Us8-nA6B+ycX7wtRBV6sYvt%TZ++szZ4Wy{6V@*{ z%0%s#RG9oFG!lW<59I^f9wX+trwkNI2yWT3l#0HGK40=pn8lipf{%VW)?TY}FE%Ly zz!7(!s(}TzLso2UN+y6VD{-^Nj%H#njYxZQZJY@0GH=h; z>luDmX;<^Uq+9d2FoDZ%fls_JK4pes0@sHYLC`UfsljE;s=#H;Agdm$w8@b0Qibg; zz*<-cI@b4>ogcs4RYHp37!)X6qAC~+y!*d9EIFevrV-;g{+m?F7)j!{9W@1c%>di+ z8|0DOS{g+{vp+KNT+6ClgKu<^NcA-IQUv)B+dVd`--R*U>f0A6*mt1+5}&vR>t6?b z{`*>zd$SO#YZ2-Jugt364%(VZaIm3l*t?kg(IY4PL6e~9b%G$9fB+<(RYN*cc|ItL z(LLfMvASRJDM2F%(?Ha0DF5n~T3U3Enn3iA6a8nVA<9CcS7JO1)${EwBQ@}&nldMo zVf}%jkAFLOGYlse)4*&K3^eS!Z2XrnD>P<+H0eYRWFw@?&zd1PQ0Ixcu}zohiI36r zVvgk3Ql<2wG9f@eD2sZ^NVrc8Z#gT7(b(Hm9BAEF!lR??!H6I&5Z|37)=M$N@`Z84 z$`<~8r^708DfVUGHACGY`t@_?*gb#FN`GeT+FVV3oPxh1tbGMT8?|>loZn!!fy?t++OV_DFT8wyA zUeVKc;*Q*!XBV`eAy2l8bMIk1;nr6K(Sf^t>Y15XWpibs^W^2u!sgXMwXRcGXyu2i zn~pF0MNhnVoezXZ1)rar%8Lj!u|g#I|#tHWGCJ(wyTO9)HiZY6Xgag!=U6A1Z$4O{WYzwgd? z1dK)p>*^Y7*j@SjOrdE6y8aY`85N@oqws`V)20ew%M8$BUCxp^bl&yZStgb9Pqxud zKwE}Ry`p2rgRq%9O}Yx8np7ck;9DhLvf>}@%;=PWS*jqq4pK?CpX`vo)MoCe=@4Q@ zw$%jFlj9!52HIVDDs`rd*dOuPo<4n9j}QiyT*|m{@$^~$??{OZ=(~N^up!h40d`g7 zp9s16*PSH+w0_^`xdn_%=n2_nW_cFB9kP^=FWr$mvYiS6a0<|?ohy|RCg=V^CElyI z0R5)DDA4nGaF7Lo;yea340o-B%Nqwcewr2DO8Z`RihGdVZ^F(4)koF-hfP6GmUuv^ z=dHFK`?>Sg04s)iVNxpB09b*%S z+^Zk$xhVty|H4C@I$j<^|0yBbQ6cs@ z$c?d_St0i}Z)EeMSL{0R**n0}OAk_Et|eEgv$ho!Nn`J{>_3ZYib<(LZXDgC)tSrP zJXoz||2%dRu(|*QW;k67#oS_Mo`I&ud^delx_CNXd_)&T`!fYZgy!GdOw6!;dl_6w zB#+Q#cWe@cai|dRoHdWigf5|>RO+)qu*OfGJj|>-#i)@m3oWAA#V_}f-o1B<_#9{x7cHJCLgQ{~tFlF2cR`ihHlUcNF4Y zdn7VK*;G_gA%tUGTze!^60#|?LdYIX$*L%%vNDQj>HECB-=EL#`~CfIoO{l>ujljm zcs>Tb9TI6R!6f*!_VV|YBGAc6wWNjLlYw9CZdVD3=xOhWe9FGaZ~cH%st2UKa|tZY z>D2%Bbv;%#bQmK?7B(29JXO#@h5RjzzqQ&P8WH4H^*?QmL-${~7uZqqhm~klA;rwvJg>H>DE~z_f)J12K}OU~9bYIjEoB zMZM0A*vE{gkl^UN@1VNf1o71yKF*B->c^w~_woFZ7hpmY6oaB-+}3Fc$9}>gXfAr& z;_eL7Rkq=5MQQ#wm9|n;g@IoT@XWW}n)wPQG^duAKdpRvaZAZ`_`fB}pPfhcHM}SC zQhF6c&R_D>d^R__oqI^Mb`p%L`=-49m(0{P-As6{AdS({?=i#Mo? zA@H3TPZdS%_UWrFUiiM^G)pk(HnQ6G-)s908LwxVyV}-4Jg$KRQdx{3IQEJ`!NTsD zs02w_7QWTVgB-F#g?)<+eq*wJ|9i$?j4_Z;+;*ez_!VAR}v)e3T90iZ(61w(W^MvNr z*Rx(&@d~#`kpLpRuroaG#sGzM-+g-OJ+iAfnslzOV_`SV<=NmoQwAk$zN1PB7 zyD+~2m`PuC&aohNKQ|ExC1doky%!WC@0_FfXIfh^*nc3#U^qtM+id;(Wv!VCwjo-F z`ZxPsgbg~=|1fbjoqQn@Bg7^3hnht!(y!GZWY{n}>Di1MOy3If5R@MwqCnMm7;HW; z;uVp|pP%gJCv5bg^GS{9q~6o>d;^&Eu)k)k7JzUs08K6F8T~x^4g?@?g7&@)Zzf$t zwd(NbPIzMLoCV3hf)>9JK)LbfV6+*9ter5xQWgP?P`RS_Nd{pWxd(pJlR;49Bv5aj z954?df{jt)`dA9h5nt>Z1f(<48in^k6k?GgHiSNpmwR~_QVpM-<>s5>}9f}y5@%vHS!zypn^W+}5(fPVI z_rrdC3ZSm;0|y-L+I)PR`vW*yS6Zk6gC-KqZ@C54VNN4)1(h^MR#{2_zhuFO(^ z=sFC9_F$svu)bu5O&fR#;ZjYL+F@+@kMl_k??X?5@j=nPP+Z3n>gE zac#0E?yA_o0C5R(Xhk1+BlSXQ!L{^>XX#s8VQD%A8Yoy8VW3ovA4!co*2h ze-N+otE*MByBaEQ%r%#X`yT?LOg z2F~ybfjLR1+r6h1hJ&V_^FIX=(=+S%eJT`NLJS8}+=aH;`g4D=w^m*_t3x=lRNV8k zOr3T$pOX#(y1B*Cq8O-}hs<~{-H(TH`?OYROOmMF2C?yiCzBHXN3o4t&PcmQijmEu zPxgEiagwUz(V&D%-Xh53WnHF=LBhxCH_kQk)%jsN-Y`lkvn-=EP@%vzn>`YCw_cPW4^8az~3 zImw^*sIFf8#z_6b2T?_E6bW&Dm1EQn-3 z6nsaT`yF9j84q>!6NhxE#Q)3 zY++6yh<`v*%DZNARQuT_4oqLApt}xfLfqDdr_BxVCsoJC_QFDRb2VW1;VU#`1;vGd z5ywG7KppwU1E^{Z(VEA|oUtc(FT!eHj#C!2a;utDcD1be4=l0C9hnnPfAa z06c#SUf6@DjC1+JD)J~k?&^`}bRtSxkItKJ#FUQFEQ4i;weU-a*qf>9BoE4p0v{gIiof9&J6U8`BS6!iKxi36AEe5I)QnP~%jvUbu3xF*h& zQR^i7f6iOzq`a*CWGE9ypZJ`&tAzC#B?PCQQJ5m2c0l%4oJ0Z*SJC`B=h1J}E?}xp z1obD?AatZM>BFw#ziX@eU6{mi{i#eWDgj!= zVlW_~{3iN!8{|ou<~YF~B6_gQFXzYWYy9V7?dlmI7iV3%#rPvGqxQCGCV^b5mS@EO z;lsA(`|w8PW7Usx&A4p_EFTktg6>_bt~r0gi?wt#Zrja#-S>Uo#L-_84J9)WUw;UJ zj+;wd8btp&Ki7?RsVD^FD)frC(6cP!`wU|YG6d|z2VOvlPkzPOe?hQeoO?IERyx~B z+PO)ZO;DXe-QQEUCpGd3^>m?aqzYLqU42(9vz|l?9kKfn@s#r2D*FE3H9GFR@!tAWgN5IBcl5lQGSCNc=g~F$Eu>T{(RV2OAy#5S^SmgegX8Jd<$O2 zJ>i%T@5EtHfyBw7#wv+^;Cx~ZXK*pBT8}^^s_na8DXaWK$Pjr2^oa#n6!G3*JtL^J z1sn5HdAFmqS!gr9YvQsa8j=bmSSbXQ&&C_BAng9I4|c!P8YXQBX+5lN@rbGS2;D_@qYJ@^jX7S4(otgBNa&ZzrI2K ztSv7exv#m6YSU!r*dC^F6VVAh;&`Ub4~_2{kUJhr40~i0kB$I}V7E9$ITYN2G9UReSt~CY1R_57;RH_vw6`TNOnFVWN-tA2I<~yB0G{0*eq8 z#jJ}Z4Xas+{12~W_WDR^*U|>KaZ()l>rOd}#=N_RZg~{*yEstPOV4CxYl|yl*$Wo# zdBJP%6ilrPbV6$`1TZ@&AnQb4f@}m>V|83M`Qr`5vTy`RLw@8wN)7LtSLMDbF zH-3pRGHo#Y`|Fbo7yIkaV+gRJC!pNTenX<0;rhV`0eG5R)ijr$3(pQ6Mqzp=TDU0$ z9kgCOE2bwc`hsc#I5`m_wLD2OBL}eT>ALTJJ0M|pGVu3=OBjeBjMt zdpf;+raj<*0r^2r(YKQGJ7EH<0D9nx2je-z7m_m zqbz=}%Gm4yIBd55!JTKE>}A8#+~a;0TvVyJq1y24Pz9^~%DJ zDGInVgOG*OMpb1-PN&+P)sGC=6iD2e3GQltwyGR4&MJ}Xy~1K@9lu9l(?+rPdg01d zw~ys?7UXrFxVe1M$Q=*L1LHT9_s+b|g8aoNw4*XLTAp#xCLO|Yc=(|U1QWM?Swl9u;XYka*ib$5MYRHCRNSB-`pD{+#YIiNRP0+PLqMx}fAUm%OX1#d*JuOWZmzVc;CL*qGUUA+NO;yOxx#uh~&`YTz`k(HBcoRrhkN` z!@^@8JB$@#EH|avhL~D|>0kIw-6ZMT(lQV9Fq7b%yQ2>=m~~P=ZqON!Gn6U-KyyBt zxgEwO)-?`vwf&E*Svq^3QEq>x;#WkLOF>*Pi1`-_9eUlsNo$I+lKn9qK*Px7VLevx zRun-OzLVU8bIpIpio%lm?S=0cT#)nk#dfN^0OTlXPtVi}o@Uz-P88ji*%e>@FHnGs z+jp&=i%4C;IM6J!x;7n9FNq>9v5H50%;BXCFCo0hd8>ditbpdCctp|f+k9BytGt&WPWqF06ps{Rzn=z=zJzj+xwtXmONJsR~MCUmnx*mYqA7UtS14Myg&t- z?sf{w6zy1}m`QniM_1=~Ux$vVR#JDfO2#NF1 zb-8KK5&pyQqu(RHd(8*-bHrU*7>;J)Q+#T~uG_2AUIe?<1k7Ju5xNR}WzSypdDT65 z-UAvXF+_H;g#iUbg-%*=8t|k{%gNL-4Q%(z78vKT9iuH0#?;8#B8VPM`VbElBUR<` zl4%ti(CsvHj0wB_n=w}tJW^<#{&6^)8PH-u&o&eKuthG6o!L&u^n2$u>YX_8>;|} z(wFS7_G6&+esA2SOybM;f5S_2PZP9-CLVtwINe&fC&nz^iVx8dZA)y;eZ zxiy&d$gjMBR?PfGxV?bizXQH~i6KQ`@*AeBlWt;YNe&SbC(+0#!AdD+4~aAifGMXH z5r3nJ{iAM7!^1QYUD-MJ_Yf36U_YLPzJs_t%z>7x+l>3Hyk?f1Ri0|!J+JtEb}Zq! zRPDn5R&xuC6yRl)>QAZ9L&mpOr;p8}{YFX>HDk-PSh5}z_ZO|ISjt$vy1EK}q9uQ~ z|L%%jm3JDk`Qgl21g`O%`&g|~&Rek4Dxct9>#1b+e~yo;nWhddh|}|yP%4$<+y?vO zQ{bxHR96*+vcG$LzqB7K-6qiShk;DY#ecKsZbgpa0@Uu?a+EZBuG`qImavv`U4b7hT=x3K;oVBl)_2Xb>k2zmQKP?R7`)NE) z4Uabm5dZN6ePDtUSNq`WNTi9osCi}*^OoM>r(=t;1;GxcmRW!S^KIdRB;U!%q2`BAyMmBZhS-Q?CyL($aGPYN>gn_nAtV8mJdD#l4Kui9XPe# z9ltq3%QXMOK$fO$^JPXieSK2HtZuwk-ow>a3ox0Vj_2xuiGPe3QAA&mIoS89#I-{E zJCqtNk$tx%u(Hlg6^>Jo_^Z`XF{yuQsjNE&nrX3TYr>+FV$swb0}7VpV2}8(;-Vb! zj&k7k^YJ;2{8eDLjNt10rw>3EnCcV}%!HN12=_AeJ#kLIBsxOVITt71aw_E97jX19 zmMu0XuSfO_NY|Zj@HHdP1a}rcJRkTj1#M=WDxPL)Oz{e%2?H>lV4?O^U}%bAXD=nb z6)W-Us<*k%x2k*0AEI6(YmoBj%^j2_^W;#p*rv2#*zcY5QrpZ=j$rf!xO!Ouio5pe z!?)+|sN=>|Jy#5h>UWzj$sYC)GH{rgVxF2K`3EDM+s;uf7B>nq5B>QAv{@A1(4bBW z%_C0=IY%(Ii}*Yk*}u*A&IWAnxK-WH+v^eeUA=L*S^QsBu*8Ya<&Aho_M-2s^fLxDJA3g-fNP) ztU~&cK^2z5K6>J|CTU{6Y2<*GP-x}lo?cy0V!q=2)ejlkyjg$?UjVC$-QS_*MvXcQ zw7nj91h;pC1jdEmxrKfdRzbeP#$gH|GE%dnx3#6R6k-7c<5*w8%y$Tuu=Y@c#|8jFGFK9$0(oQ$RJ$OOk_ z-IV)tlYi2Yesl6~LF3owJoF6q5$}_p;RWuu)~6yDPiIc|zEHRsE6rEJPu`2TU2@&0 zl$h~4A(rc+{pUh@tZI+?Sm+ykW{4R~CF1L=x9sW-5J%1RVn*f|23-~fELQawB}0X@ zq;2Aw5Oa5lDgNg{`l8G=r4J@88?H3_2V`{HK8#-4>*-hO!@NekI*M~JiaT8&ZH|59j!eGN4M-% zu5RBx(6P}~!+457TNa2nebq6F-AD*|`M5ryS$`?^GLICBD{px$K}UYbIJ9{}BDnL& zK_%shkZ(Q53-ylgtvc3Q9Z~v9tCKtWK8`41o;_@)aWtsjf^4ViAx>&`8;$=%;rJ1f zBh|QFC{CK3kX<~ohJ;QT_ysg&qVpD`x8*kNT_Q#vpJi0n+1s3Z@b|ib$pq1YFdvj+ ztwYEjB#852ID(oO*#s#GM+sM2crJ!jRX^`gWJ z;`^;1JuO*uzCH{B5T&OtmvV)l&W)5PO!un>L=JKO=v>cGi&Qrat?MvP z&KR9|%Hq?;mwGFccZ!Y1yJT6c>f48o35H}jc!45A z9PgoLcj-3F5pGV;zV`HMVk;ck_Ww??wu2fV>YLpLRKBk8tDGRmW zck8{MMGYzLyCn!1>}ah?6_Yp7t?|U6rEYoCIud!5sW5zDmX?m|{#3Q`M5-T8)~cr& zxg^i!PnBBZ8PhzRn6yRAc$2TKAc)o|mx(iS$Y3<=hsrLh=&|ih|tawc26zj2( zOp7$({e+m}WF9%=+P1GrVyZ#hF@G4gt#mAoRsjJpI+DQ981CJ#R#-}dK9WCCg#c^c=W*{_!gBE{p%_tAvW6!@S&?QS-le(_vzA&ubrTVpof)n-&JS)UUm6sYyUjoHBhUDhR_HxKQt%LMYvSG z%22wPtrJzc0?=HU+}&nUezx5mL_C;cU0iz%LxFjgt13h2j!ISJ2~k;NPsu~yWPfCp z8%@K`NYkD$q0e&6c=@hrHWTM)u@Nirde784=Oe%;(c{A*3hg?ik((t2f>+8j>OkI=dbEeU z9Q>j2Wan_I7?=TJj?q{vN)R#sxNnc4+q~#$(A!blL(ETOq8VJ^gka;Nt>*D-aD87A zbH!?a$P;7V|K)@Zt;`+Xk*rKGZpW6KlW=^qBayJ@u2#34i={(M>BsO?6Th)nGRBR% zY1k+3i-vbq2KTY%$CKl&D7VSckJ^QC6%MM9;Dyo()B2a=MZvhiPUI(l@__! z{Xvy(1Eb$2m^BGBm}AE)N~NF-Fco{zLevEC1M4eq%_L z#6)Io@SbRJYonCp*FFF7@*4U_^nvueJ#+!FU^#I#1E*9|KD6+u?;f;je=7h~cHP5M zrQ-g~h#2gBCz#rJC=X$+tlQ(pCvTQ9sMk z=}*z8DEiR58z~qHr)$co6(L2B)2hkW_H%Q<|9bGDp+|NdcHDEL8f_w0lC~(^91zZ7ylZY`$6`+FdN*>%1A3 zgFLCxHe5Wl`si<@ADB&d#@_ggK4n3k(LM-Hs5P5$f2|j5X(?V{5B0-n*3o}gEJ`=U zvKl0x-`oVoqp<7P=$qP?k~m@k-R{o{{8^EWja|A>0oy%vLwl{w zc3yi1CZPPnP?&(2hiaM^qxHe?s}jVibMrQ%$BGXigQuP;I*0hFf8OPVhPhpt|s_kVzDwS|z+3HZ#m`N9lBLMg01n7=jnZ zriZ=5crET>Ut-@Jzh9zbW!?QJ_74Jb633+;J{3A+)Io3oo81eIc)Z-qsYB!p0lw&R zny6!*sLt%nUMmOmiMCB5b;6;BYhw{5J5ZfPaDQ{;Y83SJBMgLu#>{=3$xI|MZ4_B}+dv!OEP&WEMIzYcI-0X1?tfE+4zf`lmV=!*6@vb)XML`0s{urJfe=4jru zAb(XNSLTY%_y&EMs!efy;TgM)?-$=Wp3b(RVJ5Zk_~#O$YL+8@ZWeJI+=-esW1`Jh zHLNTEWWF`#>bN0V&A5dvU)Ug97e;&QLX1@ZPW;H_1e}m8=RnJr{q60QztZk0ocw-j zC&Ksf2Ho6uRpJ3%7%Lx;@2AMvSwvpr@gLiJt8O8|u@JBY7S4HN z9TUfZZk>#vcG$HEYk&M!?01;FK9<18By}|9k!^+{cK_*oEA7>9@AgcuYweE>!SA%3 z58UT>=pI_&L+qTrwTO4jGM)^&=B^vyZk{u8 z{`6~zV7V3o9_DdI(nV$KfCjPDa3w%MUwXqW|c!_=jiENM@R zyBU4(ZbqUh?q5NPIeFz$q&sC8*p~}sH~a}vu`>-74@8mQHr#TCkqqIq7g>4f2Dix} zMc^Kj9Ptd;aih1lGe+;7K8iJbmMCc3qhWIn)u6ZDNnd=z5rH_kDIsaPtl8bJNQR;m zPptE!TrFiov_331O}(%8r}AyZ*D9kj*aTF?m#k62yCIq2@oUw~>H}Y)x^M1%w-abw zCn?k2jm^OMeo5aMCqVxSu)mSLm!@W80(tY$(fU}tCCcr^pmmZ`X2pHjwK>@-#%oZH z)nOOjA??~X_g{<$WscxVVsnMA>>;VgDQc z_s_OEsKNtlgO*}CvG{q`XbTUh7Syq~JOG^{JZ}Z;zUy^_fJ612^2bO<|KXVjajpu( z7YI<#TQ1Qv_TImkm;p1saS%z0v%CUR8OF-m_>RKy<_v0Bj*acpC){EHqfYYggo!|~ zgqB21(_0%~*zaM?J_gJ;1H;oMFL>cI^AWirg$pDq#K(pId#U$7WV3qDKEqaa|5ZGd z7`l;0j~~1um42DtS6aXNklCKz{ac=#2*KpSGz4dK)2wy~Epo zmPE5^HUC(D<2W!s1K-fY8ihx^0x|{E!O8HZ9qS!MO2YIbL~pjG^H~H6@NgQor%f;y zUeJA=_3KH-F1kVNqjb5&T8}VDD7zNUS8m6q{F{s&-4}-r1S|T?Lju^#VPFsd!(yR{Mam9V=G<2C@KJ zBByQ*t6{$eb9A#Y9%V4aTseQPK3!8#R<^J}WX_<+?l#70Cdd>C6BHzn*~m10CE--_ zL%N725tDhWQjFhMVg5S$)cc0I&NCIYXIr961 zXt#^NeEg^;uzJP0oySY#lF+nv!rF%ar28@%W_;((3*j-&QDj9kCqC}maOIfy1Nj!q z5(16E_+Z6{$YfeV_tA6CEtNI+zxvRe1Q|55tluU*I_I(;}y#X`OnH zZZ5nuP_{CB$5gaWz%K!B%IoF@JH8q3#5YrfT^VXzi{JZ>_Q@B6?>Wc%4F{*MzK2EL zpsjx{H~rEst>O6V78 zqP~~J+?h@#%YKDK6dbDO{1@ei((#R=bPhJpscC_;`Gs*#KtiO+dS>BJ>#AUiajn?F zeBc#EWxQhc;KuPnk{5H@oS>he9|6^7b5DeP3K$ogVA-8SRd|3m1)vxzv26gFB&@Ov0*VrkN?xJ)8GXy}X`yZ7)C|Vpa*B}olp60dlGT|=;gmc=(7gm(Uh!5I&@le%n;jve7G>m4YKUm^39 zjHy!SEu@;usGMp(#p8vr+c^R`1BRW2T%nWE&6?;BM5Kq=&+#hOj&0cz z?9YW?ZGlI@96ejL<07*?i!uj|{9C4NBWoSUY^U)uZbDiO|5O9u|-Tkf9>#y155sfgMW%^fWau)ec(GV6|0Kp=@l#)bLX{SNH!;h&7(nJcT3S zOm{T9wb!@nK)&eVWL99}jX|Qc`Ft?z7*^ZXKOwAxhJ(A~{gs4_LNMh@;@%7D{!I*J z?hi;Q+FiPklPGmVn*HV8D#mPM7wt-=4_>=TgISHtz-2GO*EpGr;AD*Y?~l_7-6-d` z0?Q?oS}?R1-TS-rPV)3IU94g~0Mf7XsytHm$EX+`qO~fDM-_)WQo$w-Gk&g&XQf5S z5M0q_PyAaK%K{Erf2oUq<}V((le$k_m0Ip-Z#+g+Q&Hn`c6- zqRI6}8(n8k?#;x3YbP-#p!lkgm^;&det2btd$k9BDqbJ3dcg6ms9nr6bqkl9@Y$~r zzkoc2Al(XyHRP|laIftC`{A$d?THYeJ%oumy{Dym-FAYI5?qut7yDY)VK9jC-}p|_ zxBwiBDzqW85$Q$9Ub;KGn-V1nE8}-m;(NtuzB1lErpBvV$AB0PoI4qwQNhCwpN1wv zlJ&XQU}5)eRYfEf8^99{BQ;>>Y)gmGa{UO<6waKR2p8 znB$2DN?m^jO4FR_A4q5(OL+E=BfNDqzv4A)?7bYEAc=7$!Zms z1B$#TnzX~W{V^b1&rzt3HmmBv7rvnR-*ELO22|oR%G= zKFgqXs{$PvAP9eaYy`8;iHzK=pp&R3&&nh&G!3GTlje(&tteL>L& z%_yqaH}zf#I3h%bm4XuPXA_-{ycotG78!AuBSM3*ChnlsMfnIoux z?o-g+tAm1Hznja5K;BWzCN2I z>9I+YzSn;!NYQu4Ks=KM)ldN-El&QMrNuU4B%B@;;F1b~c%@75#>k=p?7vRsRZy|= zIu@!p>a03U)Ylm1065PZ{n`P?!LfNAFJPWot(|~^)EI5gIH(1@&Gss(fzrJ z)`hw0S5Km9{;_bV&OxAvvo4IFw&JP>m~eWc7x3b$zD_uBP2&Kf6V0--~n=Z4Bqz-u}*ysv91vq zFI4q;+$%u>8h+#C?Ls0jkqhteFT>D4=>*RSqqbqFlNE3WWy~)=y6l)Z47di0xtkTK zLjLZq(hrFl^3rM;qj6yK0A5nwH~sXR@{G{+`WthpF?$rbig2|e%g@o1hVHv8U_-mretvO_@9+5Z&6AAcgKvRu&G1jZ!|T|{2{tUzbx!VgYLvO~a?%?bDf$#F z$WR@w!Ml}5FYwBTUHvLEC6=JW8@t>j=`i7nsG$jr73=d)`d!V zbA&X za1|APaT?FX1_;yUk9KGNgizU-)t1j910SWt)`31)3@JwgB8YBl2&A4=bN@4C!&t_^%ml0piB zfSg!-6$)`79`ng^)nOtg{lzh(q*^Z&fzk<)>t;qt+}J*1yWfUsy1zGd5QsrgV|R`n zZC;~(R6|@%-qaN*R;r&;AKYoI0nO_S*y?Z{gHtvr;`?Ie&CT7_))<6+9Rej;IY&X} zhqdTS#iCW|Jf6%KtT+SJf>))Z088Pg12Vq2V?3BK?HTgds1_es3i4lMzT^P|tS^L3 zbTD0cs9};Lq=2BhvxcTut6+pl7T$&nCDWvlArc^lnxyr(=8A;okn39Z$p2OWcWU3@ zh(U)*ZrhDVCtAxcoOd(Ek&~}tpfJHUda-C_-AE_n$7bHXpTS!g&p*lq}j-n zs2ntE|CP&CQL0#T9^&c?=s!@=|A5URnEaBxzF0Nc4Ov$Gx$~U1ULS@IPVt4R>bnhZ zQsEZT#pz?zTC{25`zB@WEs&ybh}i+duSLimD}e+5It#aS#z@Ugf{N9U%8jQ~C8M?a zh3Y62l_^lV|Kdqw{gbGeoS|tM`8@RgIC1Dk2r->e2rd070DY;kK5x~6ueWI_aB#i- z*WAK9F;YB5Ia}9q`vdyS+xw~S!j^%ZbP9X+bwgYlz!*FH^1}kC3-g0S;5?TD<-`Ua zXe9_ga?!vU-!m>Bhox}Sfv`(%tk&%ooSR%Xw!z_2er)1GY?D5-)JL#vu|hHmAFg%W zfb?t8%6lJ&B#jG?*18sdcY&CAax%Z60JBERVq)jZ+a|s}@oWS&U3Trl;8_6XZW%jC zlEUupJq^84>i>JfQv-w0xdM?0aL$)0tf2eTw-*8AWgXA07&qS$+TL*4IzZEdHJGaKw-9IsLk!)P<+n z4UKJvTot1`+V?SxVE&J=2}#Ninx;H9l-^k$QgcUz8-dpWhzu<$d0G)ao9c>ZF7@Z^ z*?-=X@gu})4q$my0Ebr--BX;$l?NoJm4c@Ti3nK%Kp zntUTgfi&xATfiVTBS2?bLy4)ODyYxC@3;wN(c}^G=Q|jx+>NC=0{RBllgy{A54NAT z+2;)-R3Pl5T7mH^1Cq5E6pxbY6kCwv34JWh5KI)UlWQyNtP6ze6>ORUsvoHxuqC;> zu||i>xKjw_8opta>GET)FIk07+$27Ej}rUq5iv3U)A^^u=jloQ;!RH!A6lZ?zav1L z&zGO=N1LJo%sCB3$E~RFR}fvJ_fWT?^zkQ;8$D3)e4_gY?}r1Xg%u^|sCXG~oKt^f zW=&9yZ!U!9a5>BC1?)#8=Gg(N!BCwZuG3iR}ir@#f zZZN63kEQYD*A7PHsgaA0l=b&OA24cTOXH0Vz;%wUoe=k-3Vz29#cH5YXfv+mv1${r zOXBIXg9@_r;EhfPBYOU6-j!)j!J1ehS<`KPF1+TjPhN_CFGlO)rxcu_^mCSN&W^$$ zJkj{cFsK}irSoW?*hACFEHyy2sk32Ma+;&!IG6KTewQPY~pIoXHaiJ`f0 z5%PZbzRARi3DDUXEb zyP1^w-;^50anhGx~F1c z+QT;l0A^!6`N-IVFwgf@M^OwDfa*3D>E3rM>YUP@(UXLdu?t#v_kamC-X}Ume+P?} z^F=SWbw3iDzKKV;@L&aX>;PD79gP||iK2_wpBy4he&(zDQWn>0Np5mvoX7^!n_!dt zH7r_`&IZqHlXr3_xI$aalQ7SIx7GAeE*h|DGOz+lk~?ac#5&PCWc|@W;^?R4SNBnzE1^_KUqTIQmQbpF5$DQytH=RVVH8r7xj3<@bWXDL3g=Dz0e`QAywyiVBxGx$j! znIr#fwBbM)F*`R-wcODm;g-B{OW(Fn-SE|g4|6A1%ID*V1PPQOB?lvZQX4Z{krW1S zKhv+nxO1)#gsHH1y?J1D8vO8l4Y#s#6|vyCM&r^P5N({oUzGc)h7B&Y8A+mf^!ru! zlaS`t=_cOihNjCO&74{S6aRVeLS<+IHe@!F7cKQ__n>x4&vjU(SSWw5edVl*y&!1Q zK3{4$mK6uZ(pi6?_%k zOUc;ii1vr7QvCP#XFcY%tKOe{+Z>QI<`-1S(h=;{vNb??dUX$abfeC{|1~X-ErN;2 z7W8PRK#f0In4t305u`|HzZIcJAX?4&O*GL&PAi%QUqT}eB>I#-&3WL#EwSrIxC; z242wz7HmUt`QE)*uOA-3;;&}U6gbs;#(~BE)9{b?tX2(zegk?R`r*OZw>i*p_vhfX zwUd4+(;Xy$@1_#PfaB5MUG3STG``$Sj8kY!`2mK;-0R_!Fvi@VLV3_Br9~`$0)La# zty2rbNYN%p<5~ZVErU&);IF-b&_k8pcB?z_EiEBeT)&PQ{{xOIuvi#@hW|_+dX_ZS zUF1w}Cr7hxxX=w3KwhD0r)MM*X_aGqs6u()nlt^69-N*?a|N?<{B78&cDIVT)tTNR z49V;&4qOQf2M1p8034XSUO9nOj32Z=TJr(We8te{4}I)Tr-p?LIe*zbr@s~nnglz* z^7(Tdm!Xk$8tGcy9lMIIB+tRj88cZ-baPL9KeTmZf^MS1vHJ4kX3eNO;%-X^?LKyO zpFGaxm|^F10fDaJPW|OK6<4OW%1dehQsycqunhfq!q}pi>=Fd|IsSH z?I~^LoVtY#5TLzQm=0VLW9r;6f+>a$!xq{UU)W9Db&eQgx-H;jbB8Z$%G4s(yjVZO z?g`eEUQlE*MEcU&yJ`E}=;N|i_fQ+lwq^<11K_RRyr=m?Ty{m}&kqN-EPjJG0-rdC zgL>O>JLCbUax^QJS8r>(@x-$vtN?~dO~+2B=vG*&pRaWyhEf$6JuBFoX6~63)NNtq z!q<3Oe^l8`46AzV@>7A+cbxAkA6_goGiLHV+j#NDqB(i~w~D5jI&6xh*HxU|?4Q<4 zt)E-Wa@fALaR4JcRox#UJ;0dgFkv#SJ((~mHjHrm)B%?(bueE!uZMcBabijfUARl_ z>l$AiyiLs%4P2igF2PRu8owqS*=Tk;VC$8^^p=#sJx9~tn(!flD4E1$^S6u>@2ipJ zb|>qM+1$)`KN`SdbC|nhKhHt@c9sYyFQ-=uCQ`}`=V!@79%y8#bl^6_-DyVp*FBH8 zrEE|zcYBgwK8=amfO-FVKZ(I*V=SG8;o7ahp1x#kR{asb@a#Mun`ynOtIC<|s*(ze zeLouMYc5CbYvjk@?mHwQZoF+v;Jck^{rIv;dv3rjC%lp|Nii`a$;I8pE7G4vG@BT$MNtg9 z-%!t;%=a41xa2(VlxPpJ5ya^yOON%Lw&|0fy5{uf1{Aydj`>kE$d*51avexB=qERt zv??4bLk^TQa0K2%S2lY_%6{*3lz4E0SF>5zhrTEr_5*QmAFte|n?NeR+UcZr?aF4_ z|CPMcX-PivI&~@+F7*sP3Jm$qVwJy~Ou>je2d#P{1A~|9($SOP2IO^@=XR-7rqQ5z z)IEh6&cF+5#-NA9xJ_ie>l4aDmhJculF&XF9>KB##Qn#ED{IRWToN{Q| zxaM@g@bji*YP9g-FSU%d)nQRhR0( zEfJ>$Px6Yticv;B2h8&J&-ye@UH-ued?>7kf;G<8fR>o+LpMuskO_xnCLdg^J=G#orRt5M}rs$u-qP5M?zkZV*s<`AskIL6IrmxP0 zXXA~wcSps<>m!asB*)J@O@B&nbilIt8202A{C)WX`BW@r51oe?o5zjA-usG~xO@on zw1WrP!PUlOJ@k|@ZUIe>(;@qa5Z@neU3y_?I&t;9v63X|`OM%E{^&shCXf>w_($yF zhE6`{emT0ndq_)?4n{pUfKlB5SK&>l2unEoci|u+3K=1_)_y-#u;y%ft5o|~gn&^$ zf>nC{dsNz5P%1sM;Q17|vE!yvhN5s1Zsz;?2w4!p2^ zz#h{rxXT0Wxf4;Qc|sY>vihd}Q%cl1bPYK88b^W{Mt+cESMErOsioBP)ZvZIuH*U? z>Np*96+x31(zI9C*^Y@g>Y?;kkeyj3xc1!0$MwcC_<+p?n+@8{2UOP?OEb<(C%{8` zSgZ~(b^aezCQZt3SUvxxXkT&}%;3>gmNKI#9|dE^qeY~+;aY{m$|`i=8Yc#PD#*~O z99e4r{a<@<+os z(xJu?E2c+n`OfxuC!|b@SS~K~HbbrDBvW1g5fu`Ic4+P|5_y6~(*c-%8?LnRvOI3t z$NtbF@2|OJCAh5&Q~;zqg~oM9b)f~uFcrFNm;z18zMy2xjIredzcvO$z3w(b=tCb} z4fF{&Qk=uj>SGtis`snNvWZzI>be zv?pscV9MA6F8Grz3olei_uc2MQuLLvjt_&+!XJEbOV2nG_5rIyQz%c)}Ut6!Cbky>otQwt} zSQI~#?+@Z|xz4I<<&n}7pZzbp6dLAoj?4X@zTP|@%Ki%-+uZ`)`?hdEfVa z-sfEBx~_BP7;u3VI$A)K(-p!}ct4(pvH8g{+MkeEziXiPrT!FuJDihtYGy{J`1ide_8R!CoFVf6EKs< zm?7|3;A`N8M#)gE$?^>XYNI)NH+FeW@yOl8p2D|l)c<36LuT`iXF0phB$Zjv*PL}m zlW``ZjOa4}Hf#%^y}?GBrn(w;`;f#HyV*y(v<|q@BdBV7ZNNUzjd2ta<-atj+Xrux z2_satyP_Y1Rkj2c{P=lXM|Ysln7wwuuD-7@bG7~Q_0?wk_TS%Ku`0lP5hmO`+IrWa z8~i94NEr<9Q{+)I5LbZC(A&ooyI1_{*pEmYoL6)rdXU$HbLo|<2P@|go zd0sYc-yYJG6bcX@YPN?eN{P4v4)Blqc+#5Vwn~&ncfWR?`B3>j@c=T}pnY$H$tnJ3 zWe*lV{wl-h5V<7zY_Y4i;ZtQyg7Ed8BPF^Q69Lgeb@dDwXXVe`Fw2z__4BvdT|L|T zi5Bvsapi#!%3qoQ;DvR6$c1K5e>0G#bm8o8ALkppptC68cfl09g?Js|cz&Mg~0cZ{Kujg;yqDU+j&BkftW4FEdAhhJdvyTK}K z}`7~HTu5(WAN9kDBziAt)_j7 zW@P$svjtpNC{?`j=S&ET0DWcAgE-j?;PSg?Xu=+ zBHc0oT&I@tm-4+&1XIxaQDlO+4K<+IYWR*p!Q z(p<;G%Y8x@XoB#0lpZ}?Buv6`BS-B&_T$cv|CJ;s3>j6s>cSgK4HAYC=kxS^s~F3o zeFeaC31>TzmB)YI;1Eo#NQ~J$-xsrc9$1;GPXDX$V;%KbvDn%6EWrYZ%SnExv$$w+ z`_Lij!m6<_Il>si>-88W8f)?iRZk?PR+~L%E9-*`M{;wIYM_~FfQ5UOHd3tCX&H<{ zn>gU+jc_3sB|t=^`z+ioIUZl_Zn%>S?`pNlw~$(ri^jHFhr7l5TKP&&>_FkyYuq*> z@=vKIS=bT6MX$~bccxK-1{UX>PO1H-K!G_Rm!@J-G%bcO#$TBgs34&32sG$MLe1-w zm@2hzm?F()MI@qs-8AG-d#*r{!^IvOWY#;aC^}myW%DO;pFH348=!?9tZ+;8GQIdT z^3nG#4kXlwHR^Zt=iJtP+h~(x67g|j_rhn5bo^o$b&+2`OU^No?kcPV4!3ouI4VNO7{ zQw0BJne>bqN7w!??dxEA1$>m5_uNDmBYMBZXMn5u=fn6bsU=dEeGlzb|2iYOPve@C zq@mI`75iJ(H^+~+k9yZT95>pya`K$D8*K@UA36Tmzicl!-=)7uQIvxfTR!3@p5nU; zg;V2@OA{hV{if_m?1NW}x_yU_&@c8xODE)0MM%GWWq_xp>|?6Q%lM?S!$}GhwRuKW z7QFbUCg3WjK9YV5rT^*YzgIm?>wMusbl*+%)?R7TgtjbFOv3pEW|@(v9#&;#Q~ z<9*)Kc^Q8yqLSW<**FJOpGnh(v*#V6v5HIoI`ox!wpy(LQzd2A(h+#P;C`?BsIN%A z;;p@b%2jzgUcF+j#$FCSif94_Nwax|eT!=94P&A+H*1#l9w==gpY66NtLFvqz5T#^ z;;Egwr<4)b1$)JPyjYrJymc$vA?a756)Xv&xAg08f76%0MO91FZz9+2-r1xm9705| zr6{Rx9bnO%*#-|6wam!lazO-7G|Y<;o-NUcbg7e1Ez+g36lx^HUaD;IX8%-%k??$AzS0 zC2wI%sgF<2UDS`aT^JT?3o+CDWLz zA7A-0tHbu<>3v%DE(C$~_?SW-fkq+!x2bZTvk0(M(u+ZukHcpLF3|4*&FPlJR-1gwTG znPJH(hUtSDkc;!A& zk;gt7ZfN!fB-Fiq1K{uBHhTk937K7lPuU(s_W;%k2NqiI5;^+vaT7s@-128zWKH|P zXNvc%K?`sAen$fnt6E)oUEj@pVLrQ`wO-EW4{wA~7<)k8EA#cz{@`XI(uxq=@43C+ z@g1O>b(=*@SXEc~ZckMldfK2?i?~VY)_5ji35v%`4;ARd&3Czb>Uh8StDq3^w$R1}h6gY=-3lOOSM*MRO&@&h zVfu^|Vhf{G7K%ZcQ|ahARZ3D~hLhq0YQdB~y~Z;v;SuXBr(h{iFfjQ3`VO50ta&mK zR;H}^lkST!Nb_L(h22~D7eG7d>4(1!Y9qc8?>|MW(E3h(s$Z5&#HtmS7YO*aLssF& zoMQ9P{O+2wTfK0-ltph@%}sgk9ppm|ZPip0Pyd7~&bbM^I{(nUV0qZX-@fKW0UVv0 zSq#QUFM)PWz#yg(3hN6O%aBaw_vZkGJvEZW>6i9PM0&m`+~w>&%+AEMgf`#a{z0o{ zTJBw?(Ha`|j>o6itA(rcCGjRx4vC0l_N!&lGwRintxa;=8~M~|qQjIv8Ink@+HYFz z@1G9`zMd}pUi7WV>-glrs5GfN*aq$6z7p zp23$D&g~tRQOoT=k0rdwe;Fi(lA@e?qx#|!rkMl&?Ch6IZl0}>WiT+d(15_kgx(3G zUD66jvLCq6CiJ$t^g}ftfL36eHWpX|r9>0{p$!xQHNuzOnuX!_LIFju?2f|#lISgb zt9qkeV8jI`jd)CcJVR23Q(ySKUe?{uFS{S-_rRo%g~go&!8Nb6~~3;yToJ?le%jQi3pGkR9~) z%7=;z&>3gXD2A+pSwqiJJ|5#317{Z4dH!q)xOB=<=rmvp+R+zbVA#*)*!%VQI6RIQ z7cou)0#3c_BX;N&rsgOfIrQ|B@@-mF-cB0|QlbA^owKW8on@86xMM0Xvx|^4)`Ju2 zI8dkIOolM>q9%$M%&(;b=F-Y0N52YoYBx>}e0+I>Y4)+DUm(Y5p_e<{AknQyo=6IW z2*N<<;!wii{!VLIecOwAAWhK;U9uK2J7LaJrLUEMD5tQ~bee1Iu3S*V8zAIqXbN0{ zxrEl4H-NQMwNDrZnOOMzWDB4Hu*UG~7nCoke`<8L9Tz2dV;r$~Tr#ubF)=O__$jm# z4ONPPR;)B-l>-zO@5|ps(+N{LFa&D=*!x85OI@elf^N~&%uFrv$X+lt{Jt>Yu=g0U zR8Zb4nc2DDDAYNtM2?zruOvONUXG=p3u9qf?Lxb*e2@MiHsI0L?91vW|A4P8>AH@? zoEUKpmqR(W$P!H?Jz<3k*?;Rft zsy->cW8pSJCq~C%#~Qq7Rvn$%FyMjlrHC_e=X;}$?^Miz0jLmcm|2R!z02crP;!UH zUYNglFgg&pZr44J_P$B`@mqf);?|#-uYBEpZBdv0d~VG+wNa>QZ{<)L9xo$Rdx^;REECU9bORu=4vVnmMvjVH3v zU`3mVzVY{OFjGt3Fof)}H|uAxL1+%0PDy?c^m(5t9m{-ybqBY6 z|B1xSAX*Fl6Q^fAbo#0if-5kJZ!^BO|18q*pRfnori9~r$j+E%S@+hBZh>p=laJWI zC?yI5wGzG=HBiixPaMb)q8|0N&B~fX^AXzm?Q0xu3Y5t1C9itKRSrROF88j`?9S$+ zE8@W+!Ol12>u%h=Iy^kR!IjzmGh(x*F{^RoMb^$nf z1(}3i>Bww_(2CM4gF@;;VH7|E9st@ro%{&JMmB^7=Dq;{=Ed-O{gt2YzB@Y*VSpn< zc#hnqSD&h_&j0+%SJAfl)BNBTxq)L+cVmHvjCN3MfsS#7j0UnesBXH|$op zQrY4N+c~DoT4$~|J29<7iNMjvUG@|tJn_#$`DeL9{bqm0+~){OOPOA_;1_(u)lofT zfX_0*1e6ZGC%Z9yd{s@mwAsZF!#F)OuYRkO@kz|KWFK2&Y4Zb@&e%`e!hXbxGK&K@< z$V(`w-E;LCkTfpOvpu|EGxSaWlL(QXpr9dju0xv0V;vDllc^P0#ZF&j%=9={V&IZ| z4(bnPT3m%y@v#Etl}8_X-cpkc;`VEC#aQc7`YPeNP#$;HeB;*MHVLw9@AZve(Q4GZ zT!OyRtWnVUr^FPu91mU$^21C)Ol2c5yR-nXaH7RvzOTAOgboEq@V-Kq!J5i2zecN$i(*+BWG5R+mvv@33$kGcpARX)1T3s4excx&DX0WfqH zI>NS%-Zmb~afe5Dim16~_|@Jwvi|jF!tZv-6uYLhG7(#YWBi}zWY*^y-)If6OW5H=W+Jjkl*BQqZ{I$!H3e7#Ih-s1 z#Y)-DGknuJa#}Hm_>|Fg7@-{vJ|{Nq;n3YyzO!-34qjETF*&{luWOu*Gnb} zGpSO#w5a`f{|Hd1wX-w5p2MRl1-)cC=spLF%qAp9;oz+=BZZBrcmh9 z@4Y5o!COka7-^Tehi?4tJSKf>*U?eS8JL*NTrj(XiHBlgAL1;Q5yJSc=JsDFgbW-g*CI&%Khl$g^l{? zB(Z?L30aeYo%XX1D_+wYltrc!+lhB88Z@l#AH=yU{>Zj zH)Kfo8u%fh(!2VHVfxHrBo=v_!uSc_-JW+-U&G+|^}96e650O^T~h^zM^U3OJ@gJ} zDWk5dV!`%!G`4>9(Iqn?y*qkK`W(kvtXpv7c{W*} zHveuL4QKDj#>j8l5RVfXaCdkZy*Ek;T@QgWZj_1NGQe^c)=UTc^XpL!-!zHUk|@?3 z#5$VjNWv-Z%=EL}xWh1|Btvk6tyd+{?COuOj3Jhjat+rdT+@ zk+{%B8)suWG%IgLoOqkBplTz=^*GQy+vvI-J8nfARipcLUE;^rP0+NIp)gADWSB9D zm<#he4zjjM3bdd5=6ZxDraBQzYnz>}(4zf~IHG^1YYO;n)WICc-^DT%UIY3>O<_4m|Df+Q&6-@C$Y69#Vc$Z#qyQJ^l9WL$fzo%0!5=GL@y=SO ze@P4%z}9@CM1YdR6^}V50BO_hWrf$w#dz;13R`*EEu9_64}@s;fY=&4WZpaV=C2O# z&C%`$CuOtmhCde{ph1@RD`4Qy16L!%Bj-`h`t%Ilh>mDRxom~GAaurwv$K7fPsh_J z=(a@IriISt`mrZ4z=6|~Lz!_fQZMi3&H?)khxghh;t6K!m9>@x)G=x_weMo<)7|lu zXq%xQR70I28iv57+o<1HXu+1+fiy=NDV2w;;7<+UPyKYBuG01%N?!(0f zVEc6kF*XzuLn^jEVNKuz+czRC(y_M(Yj?p^D#L9aTy=Swge5(6X{=Q3N6fhrOvfvl~RkA2w;u^2_3jFBG1A63>qPrmn4ccHi9e$eBQMuSR=!6sa;z-QV zrA3AdDCR+;*JtvLJ-!2Eyrt|vukJsemxyH?KrXD{)+~h+qavrhIpY#)-$+Ut1kgzu z(s5VbM~efdQ)ZR88!3BKbQAo#>Er4Jgj&hVsv;P(0DiFXA6qRz@o63 z)V+?Ux)&BY%%92PR)AGPM>Papst7*_~&TCw8-NvJ_j-9KwD)qF>GhJkMem9G?#RTFT? z^w?OLM%_}4$21GTJw1MK#?#19Ckr8VQGa0sl$s$&b+0)KAR=c%3=4qH1_vZ!b#&d7)Z+@y~9+yA+W#XC%pX6QZ&UW|*-y7iZ zTun=4M)OP|<47QvAtH6l7wm_Ck)9JzF~P^ zxQp6x3llv^GH+3p6@0O~{<)pl?C8Y%zZE5AyZ=-LLY`9rv-PV(${isGb^;BKO$2M`<7% z;xIi_CQX6fV{6U+-cRq_TZs;Mijm#Xt;bZlDEQ_-zI%YuQ7KTir_WTU`+fx)d7;va zoc{SpJbz@uX`>@df9@W8lIg%FJ9-H_x5!`>p4_^hR;+@$J3ZkV{9AOjlh?ZS< z?K?L55XQ#++{Nnw8Q*C?64a9=VjRoMzI6eEFJ#Wxm-FwC@^Zeu!YI1@n!)dfW$A&% zthWc#@c8|#4Q0sJQj;hex9cY0)wZP+W)EVVn|fdRkTFJ#dtn~%6?2dR3OEgWs#~4| znEqyv2}BPmN|ZiCLpQ=53(cl5>P7L`9UkLQ-wqdfN;x3o{!> z#_%_tdUtp#ZVg0#yB55#r2s>tg9JZf8Uk(H;Iy8q^Co+Rwhy3P^%)Kf0s}d&!yV=% z9T=wp*IZmX*aYzf1maw4a#YWsGeGpcAN(DdZYKo-bW7q0ph?rmD{9aR2Op{y7uc)Gz(cU!XWweu^(1nj)W7l3xaYztra9f#R-a+N7Ute}aLHaCOXNT8}SP9osJ zxy6}lQUL$Tl@cQ+$whxRKP#`3jcGfj&j5!22E(VHoP2N;Bq=nxhkrM#&3ckG_~BK_ zfiH0<%8-CMppQSa!_kuNa+;hh;3(bb$BGIok?zvlxcrGhTw*TeJUea(PuX~vPh{~Y zY)U)x$wWw=WK=cMVr`A^t~RZVE}sf5ofk5%)oX}wfmden;EruYzdVP?Ep=D(hs0>> zvu!a-$J!j*X>6lFlY@zJ($H4Vg_XOpbH9Ka&`;gDyr85egT=0>2K9w{bK0O1=YYQa+OW_h2eSc zm%@p;Hdov=3K(~|Ni_`lx~4?$$x?34bD{MIe(8E{webC7sFmv@<;ziUvH4zv%eOcp zQ=P&DKNRDRY;rN~b3V=U5O&vLKrnnJ8mqtv!5X|&Jhb?&ufbdM890yUky zKQ10K76VQ|r8triB-XS;`FE#2Fn+ml;4`W$=DRD3vZ?J=55w$mLRE6pz%wOQB~ldl{*3CG$Z=Sb)b$BWWG%3VDb^Txco1*7yC z{^|x^?lBNHv;nf#$BkbJs(o^0|u-P&e2-yqP5R^^gv9cb(79B@*|H>xhbH$nh> zO^n29{>tf~4Q@%u3tNQjk z2B;tIr#(+j4y{PXk{K_?H(cZ1z9_g;?|6bTal|XuO&rdU#6WD$(BmjwMwDLR<-yfk z@P<9j0fz*wf<6A1k6h{uYyBr6KeX{QG}Ot%=reB&8t_z!>*XwBqqX_vXjCTa#AqiB zp56|sxu=C|pd!1nJ7wk|(rN)Sp+>1NV!U7W8$F2wU3eElc}UnRyXT(%bfdKL_7ZHD|I)~!tpH-q6aq;{b2u7ON| zk8ti0Ng4CpEt7}4-?gu~n#4xDHzh#DhoWJal+vA-q`esq%({X!%y+~0g6udG4P)IkTO7vm0Ks|6b_pyC)yfS4#PlWe-A&`)z7@6@4X7dr0QfD zFHrdm&u!`85`iIY_?WXmt~Ktf)`qOiVR3LGa@5S*?L9~a51JwB?RV;b2+Hil-nOm0 zjL11!jr=qw_MQxS$>Is%Pqdw-&tH@ZX# z?7}M`Qz*vb7++$epJ1lzD<|hdI?b8OrdPH~u`yI6$sNP(R+pRjM#Th{>f$sgmD!a0 z;*3%?u|}AX+?~`83p5bZl_36q&4a_`Yo(CDa_se$Q!S<*->&^%hY+A*nX$1k-J1Z9# z?@d7J{2E&dtnvd;XUai>V3#Q$B{br!zds)tA2ghAml!>ciN+`%fACgFmx6GBXx4PyVfk^E5VWy?|jPJlk&ii(VYS@~F>3owl8FH3^K_b|cs&D@QtX*T53M)T+ z-m8CT@+mD>{u$7Dx-Yv%y@|N;nuCaV%nW$t^&ZhKQUtN346goH|F0A0j0_VdJ*wea zjNw{*n~*diQVL?Pa5h{g+KvM?sGV1oZNN(dY5nOpI87Uw7v$oG6*+i5+z%TL85*``(J+j65fo4Bfb!9nk?Nn11wK3@vPy zrlOJI@ds6h;E`R%FlwuOg!-pCq0WJs$H%?J;{pEm@*SN~fn?zn@PPd_JS7_x*=z}> z8nRaV*K<}QyR6DHF!%lUzT1Bs3gLk58Yr3fw{CCq%R05bynzS!hz- zzWL;(>cr51;&Dr*!>)IN=F9}ff4$K8im`tSrNBWtlU8Dl;4BKIe;)Wv2Vqz-Oj$B? zeh+7uC1Rrl>b zSM?FoW5x+UvkZrzg0<(-ik8YF_iFK8>?7NK@wt#0(FYJgncQRHtkl}WO=gJCTW%2Q z0Uby-m%yu=y5FBHxD1UBx(ny{&AMr}2hL5>qYGO1aBMrcvv*OSc(1-|(jQ|ndL26=l^(g5$iWmSBCZ0{4 z7`+;q#!o^eNwHuaZo@zjdnFYq6?B1C@M4BIn5<-qZ+wqli{9#JV{QV)9*?H(eJ_lmrJoLSa4zawzaFe~@~ag@cmL-PXy@TYr?e4bv4k?_ z>AFC2XmUrL*onu9&iW%<)qOf1UYhCFm@z}njOU_mM-)SEz5Wyuw9kvgpw?6AedcH1 zcdAKug2uc`HldzVpmEyR{Zhv^Ywj%^j^&Ia2#c34vp<#w^77PP*QtB!Mv>TarE{1L zi{47_?=C;NaKl&{@g^tt6X-D6>pt)GDriC+!TJP&3t%7UjH|>I_%eT^b-4pM zkAkI61i0A9QLaPV@2Ljsf;Hd zP~aMY(}q0gP8{^6=}ygoCj_2n?LQwnSHot@w2Jn60UgVmivrZh&X0VCVnCFwi5ji6 zF#xBBTN-)-a`q}-tmE>yI~c}?IHrfUUYEJ`oUl!VqSp@Nk~l9#A&~VYc{QC#;OsAl zc$=Z5Hy*sDns;WI)VK%7de$);U*7)qZ?DxW(RGG1@ilyuqMV+}-(@GGAKT0+qSiBX z*)lO&2e%@oy7DIcU6`DfAHIWDxtMd62@bPj5M*?21@!)UX`?4$wUho^?H6`WoWu~6 zD`FuA2I;;XOU7()|94ksStq(VJne%|UNI-~iydpbjM)(U@4xP`zM0|hvJal+lEEdX z3<)^k<=22isR&MO7yrSj&JzE5Cur*}-|d4&>xhsr$m2-3cD>|J6mM-LfZyI z7R!;flGFnA5Yml-xHKsc%z79rB z%Ofr&m?(|Usbg%)coerW!vy|qdP~Lzw1%Z15ncT`NqYu_J$tPxFvZr45ZHA^GRc~K zMIQ8i?4<#3n@_WcpRglNaifViCd*iGGf{w!9tSoPG6*>}Ak93W^AXSrkTs~1BaplS zX5MmSfPqIJZK^Zwl~uoLv!&)5>DFtB)?O#xm{}Y-XY8ewo+9{NWx8X1?TUWDs}h2oI|GYNhjd20tGdEhaD86^;&J-p6Vw0hqd-mm3^`%Cimons0 zAVfq3-Pa{%>;s&89|4*q)OfNK5iOu?(hsdRWp%5MFH&WcGsMb0S$e!d-|OI=HYgZL zDQ8mTOH8%t<~M6)qU?e3N3Q^k^But$x)pUdXO4;qc()~Dur$WUBr-84S}|4+9l-}V z-7^f;oRjPeQ*3UPsBA7tE&O(qQa0ifZ8S1cv)Pj8wRDjC9xNoLBZGz`nFW%p zQFkHPoOt@R1c>i!i>XJkj9x@+l5li1IR)pWaw+8N`=dB~q6`3ZMY9@|iT?OL_41w> z68%U10*DMy+#}P2X^qFcmU+Dl(I1RyB@mXOlowc!oR=lw%sNh${}_Yl?*Y8y|KsR% zq6}UFueRYcf)PnVrZY3~yq{WBv#e=Mw+^J$8Kv5gX8Ri+IcYI5R?x$MLV68k887lP z3>)ycdW<)>0s3tkJT&?`^8!xID9p#p*Lg3@Rhs)vi@Su`z#(39Fi!b)5T{6!*=6#_ z2>ni7<8QM#3i?WD(ScJ|Wlp!>{LJ|-i=vY0)WjRn7;H=>_TM;Kt_=+s%sDLZchINg zc&)$|(+S4S6?7aM7r+Iw{1=PV4~Tf35JC;UFB>s}Z*A#vtp5z)p4d$qBrnx9cPpo^ zu@h*LXV%`L8p2f?%2X>_P1y2jw&_|~*6by|uzr2xzpi-~lYk70js)$m&% zJh1`|_Eu@s=zjt0@YyWQEITaBiOP0=mS>4b9&&b#tMTv>_)a9uXmC$JThT&1{wN=# zAC_FZ!#?BZMYx=(ahgNzcN#_mic|0<`uy9(i{;EGw{#dr1u2G2lsp zSc|`HOR1cXf>P~1xDw345Hp*j0~Zsc-(bmVF98C72K+tF@M0_hJC3Hcz=87OOXB)aS?$bUSe`r4^uL1HF1YM11 zbT&Q(@d5)Jpx4oAYAd@Of%)XB9qghE$#t=s&^~B%a2HD4pu%S}1#OjsQ2`pij-?Tj zthc<96_cWsao%7OnFDktp!!J<+dzj7Kt21Rgpd3}5s`op`9+^uQbT77n^Ahah;7siDE_fYVl zBtniFj^N15K^G&kRxMxc}$a!+Y;?+z@Qrd z)TTQfZ-0Y5NArXiMpqx2vY9lbr2-S^2=M&Uxj2tmqQz4f`o~m$+IB%)bpQS_U-NVs zr`R3~Xpu-G{Ez1i(<@Z`9yI6^k@{3{YYD`HCsQQ?cUv$cWmpUAw`}N%(h-;KS7)EW zD8`LHS^d3P7_F(1uj38Iz?8r4xe7OL3RS6u3Qhh%42GJ}0SRRFDu;f-Gn%M=Xu0pX#%?F zPoh#eytV&$zal6hU>np|J)TA?Vea6Y{|Y;`^SZnGP>^y7#>CxO9%QV_|CD3}t5A}e zK#gLbB!cDEk?aHW6kcrO*~v%;WJWx=MVBCfVYzvR`xFVcB8~zV#0N;D2Rs01GxwVc z?&En0>O-jwUx5?GvD(z}mP|mMGMs{p2I>6do&j65kekhJ5V&$KKL8iFETkAy{sP6= zD&%xefX$y9fPSA`eX#m^p&<-DQVIhL@{RnZ42&jY3>d3m%)0UC7;UcREW$UFEGhq{ zcIox);_!=#2XE4H`~eZC;-xX-dQr~%D>4s8LTZ9~Sav1gfs>DJrfwOi#B9N$+oPVc zh7g(#N>sqU{Pdv1QE9+~Zci~!gDNd(bInKK77O27XuWxSecvwkW*xGOIdGP-`>PB2 zOD0e!Q)n+cyRKgAiXvECHJRJ88odHRpGN{5g z&(G)l<7i4fOCP89nR$!fGM%){q-ZWkHPN@QKxK>BCaSn}Fy#IbXR|C_uc+XJT_tDQ z>&R!Yx2@be39P{JJ*?ao|4}1|47~K4Xn=)sfqZ;Kr`gz;gbVuE`@x?A0O$?!WeSp>L^j)^N(18>tLY*pkxx+^9o4_uY*dS>!8G+bEkPEkV*7DljMI% zt+)N#Ng5)hJsBWgHi6dMHApq?K2KocL(Y;&_Wp;dR9{y&t*En~$$eWD0zHlAWC7!1N66h4T;a$T@h=@_$Z@HP{ZGd}z>o-Iodz%yd&#!9=0mWotIrWyhfqw%cy_|AR}D z$8(rmz^725kSl?RJdgZ~9dK#VKoGT!LpCaQL7GBk{eF-HQ2?^=Tb^2a#|xQ;Ld@r#W)@77MM!>rey#(dwdXRXXK_MCrA<8&QTh$6*tAr}aoH>z< zoo4i-`MjOwxB@(RvHY3Ol5hgvgu)UVN&BBg@aHH>e$682oNb zk*RiT6j0{T%BS!;8?S+%P)z8WL%|~{Vlu}?`-%(+B-RM;4{sDb4{Z2VfN{(qpP7vT z|34RQlKEMB91fC|K(Kn48(>2Cvp4T2su@(y#cL3-*m6K2&+{?V%K5@wm0d^{x*X5& zzVE@Wd9n5Dc|aZMFkq*C1Y_(xSSxe5JSiB@=4l!82i_I1#)LNCPN**rH5dnt!P8+k z!EOoI9KytUaTe{sEYV7^F)nb}b28!=J0P&S!vY6Ei}K?{Q+4CXaoguj;E#CIk+3S7 zt9T?YELFTUu22|fB91ayy)0uX`f3{dQft+K9Np&hOM+6)Ieypw3J`4#e*GT2CwqGA ze7h_VpT6E{;-EvJ#-eG=Db zlmV0ZOrRPOQ2jJm8mHEvzw#rARSgN`8`$W{7f9im$Zz;6WcEW0xjU}XhJFoj!ed9v z=OF($$j06jcZL>0Y7oFBN~f- zqU1ydR7(g0BxhGGIR+(VE~&}tOj*O=Wrbr!OR5kpddKk_;MD?6u7{OvC-8e#CgXrK zvOl(_AE=6#*v%6rxp{BfR`czjZyOec=T58XEGTd0WNf=1ivj1X{U!QcOf(n-_|#!q zZ~Ip|%&h~mhh5cjK+8uN{pW-)x1+n7@Xi2>-5Ws+)VA}0v|tJXb99((e+C2qr~d&D zo3ZNb7TEv++Dc>ACIchE)774e*Fa^=Zen(Owbw#gfbR3DqnaI2_=DoB%6uJ>%6f{9%axFOq6SU&1l$nrI2BR%@SrCiK7*YhQX{fT?d7&dg7% z8pbJabZLgIR;WDzUA^K8^BUkQJGZYN325Ivr69@^dI(FvGGNoJkN@2e>&j#0krdB= zaFDulwCP3;<`Jdk!}v4DiKRF9th8_>6NZm6jTa!Hi9y+N+on(I_Y*W}gM(B3r4{H2 zGB%ej0m(^@Ts`5f2YL202r#s;u(S8~7!#v&{suBALWZaIr1LBrcZCXp?Ba(gc$*1W|8*u(Nji9olU* z6G7f%J#awhq1*n&BYtjcV}Uu7z*ab%eN6W6C`<+LVBxyf1PDp#XqxVt_)6-o}e z-D7xKzN{3#l2M9_=kR3%P1f#NG#6(dNB@Bg;A2&W#f`b7mxjeo?Zd0$pHlEA#TPKB zY^A^Yt?D#zA!aDJK;y>f3|o@j;!7AYo6yILBYnjkNX9rO0ktvL`-}n+OG4o(f$w{T z6#KcgpUy*N_LRm}d>o8q<&p~XT!?5sT)*i?l5%jLTl)U%7~cLPfszTkxL%XVCgfy% z??7q$u#{Y(5yp*2M2)Id?8oQWNW~mqbENSUjy3u4(9Qgcrs7bx>X5lIK+A>$%`$H> zk~r+Yo2^H5_qXodMwYpmnD`?)yx|nT*c{Hz9#cPhiRI9B%366{d^+bSQ>X3;p3JvA zbW6X(8Ow~<4{9!#>tQ7@jTZ+MTtTo&AK-Eab{8sJP$NObKy}DFWv_s;EJ`0?d44m& zGNu!-$(ZS9J1X?~ShkM)X?6L;X($Yy8mT?{Tg}c<6OnO%fvr0zAk11Tqz|WN*vK;v zmob0m^5|9bjaRWE;ZRyb6Zm&lcMkQ9-58Y-NsqH>a2sKdxx;7$GjN`X4O}Sis@so*H2ZgDxZGmX<&e>x zPQ)e(N{!iwhzi`2W}8#EW$8A=OSrYW%h9_5@^g6rj}$F6W#>WJ=lcbJ8gCDyTkM|v zZp`a9p|6G49oXV-D3vkaR}LwFrWk~5udh5_#%Na~yeN%`ewnXYZ|=9pC3#pz#b3=} ztzd}CY>P|7ll5F5Ux_wJZ@l%sj;cek#n^4!D2@`%ZDAUPvBD456~ z86@YNUXREB-1|6e_VXgJ;PZfA?Ug5uH#4?X!a--nAdsl#o zkB^D(_9G9bJF?)vcZ3B>i|G+Dl^i57H?WCg)bHZPJfk3t*+kroY3DGDX`n*Hgp=<6 z$8{vu-Iz}tI%T)WrLg|v5;M3>v+RgM^*=ArVc!t|H(iUNWydYcr+kAILwAL#?86N* zqW>6yFlLGw^KgwaBbLWlF}imVe`j_j#)yg(b9>AM>+*m8yo{FJ=szDx81t6nW?4H2 znB;#Mr3}TT_@8$W#pH9}0MGvOn6fo)*8g@VWsD+|ZA{Ix zWA^b$%kl)>FaG^Q^}GLGH_S+z|Mfzs5Z2&-yHJ%Pj0OL%v#nYd!NU4)S70%40+NIx zVJyRh7%?mfXy=j0*`-T#my~3swVs=-rr_0UKRD^6Ri?km=xo^oXVZH5S@v%5^FYGH zAU-r2g^tenEK^Jf{Dtk8ru|~jrDsDmg(p>dLKDGAjLv-5%_DolOG`xgvK9Inmo^_up1NLv1I)*M|QZ` zO0xDYQsQI3#L4IPswviY9)B(|h0X>Rz9d;eXL|`nAA8sKd1U-fTyB42cpK;k~ICH3{C1pE+s1)}}staXtqV?)G9|(j+J2IrYu8 z3v?j_nkK zRSu?9!cJLj>f<7%ihIVDwuwZv662{p`}$r-^9go8?hCr|WH8@2yL<`BY-I)7n5)+N5+bRc8=E+n5iS4&cIk&IUxFZ=sG}gC7 zTv#;=v}}3t#E#}-?8O>(zpGUK@?07DP`7S;Z%TK0Fgi!-gTWUurZ%feUG17VF@i|#jF;V_4No( zCbMTJ?WjH+Er04ZWb8ijHAALIzwEKwuvt(|BroU75#~aL&sMLp@yM9~ zuzA=fzGCmw?^#N2{o)71Dek|XihJ#s_wqE2=j#@yCVY&2>In0`I6H8ga2*;sJD7B^ zO7p2qaq3~~+a_~s(Y*Vp3to4&KepCJrdF=PUDKw|F&oc_o*A^rcgVuiVs>Lc@yepg z>4D}0n}M}iQyRNO8Gc;;krQcGJ^j*yEywn~UfPF-eFH1D+VkU;wcqa|xfN^J8Jlp9 z4>mSB5WXR>39!0zRZ@47#Jwu1WDaFaeD($g3v`R?6K*`lB1M^f*D_(cPnX+;=V`3e z${E#>=KjlLzlWoEcEYI3gO~f_N&r7A?X~ot zu7}7Lb~G(QrCxNs+QPC*c4mVV74`e7HvKw|cYFB8p5x-X=V{3t6P0*^C3jJf^Sd;#rl2XU5{Lf)CY6sp_6xg3VSCkSjoC0 zZ%=`t%af{gM%*$UN1g`7X5RNJm4)7*5e)LfA}fVtH9hC&CmU`*H56)IlW35gEtN2$ z=>=W1GOFP)l{R#ono)I}lX#lvGTUO8vUeK0cD^iWd!c^Wt0@l>@!i*JRg=C^h40uc z?FFybwWfNl*L2N3WVlqvi4?UeP`%N3V*B|GFE@Mk_Z}SB^U5I;uNvshtsrWr z;7!J0so@!>)l*Wmh{k;+I}etCK6kKFi$lnT32-{Bx@C`6I-IUYWdKJqFns&rolDZv z@2c;`SHS80zKd?uTZnt^KErClub96h&|v>q^8D~!!{JPr8}JAtG+wLI*oJKFX;O`{ zDvjIWl3S0;{mw0Go~{m;mO@Xyx{cXcxlj63CDp}d%3SLFo#fCsa)U0jnp%g3Ex!9U zA)JN7n)s(a9#Zz}c#U&KUGwY+ojmU1B_%=+sj#W+qiY;TeUdK}Ro*M(D2;=`!nt-F z725))yCSF@>UoI=xI#oe%Fz_i52mvU%i{({Ugp<9_KAdjAM|uUwn0wUrQe?Kq+Q_H z)qOaDu&MnNzp`<~v^y)3D`%1CCqLgudE10f67}BK@Wj%RCF`ZQ2KBK&2)&9`=-f%; zWy@IEWu<~H+9Q!XEiu#xRo=daQlNH3dqvG2WX>sEg4oe>WNKp5?(aTui}<6$Vo(XX zF3n8p{uP4;y|;pU`XM34cs`+pfZR{Y?JQDlPdKH8#yiDt`5sR9@sY>De*QuQ=f)+Y zIMV1YGJ^ZzIcKD<57;DdLYb69we7t;0+tWI;ZjIdXU$GmsG zOeo*urI!zy@T6BSLv4Q%oRpoh<#Rxm_pleVt(y_okvVs(okC6-x`$q2T=JpDzSAKr zRkEo*Gq~;T^t+w3(D0~DanX?kwoEkZm%}$sF7leB3XW4Y_wKHmv*2Z5ANZlw{rwl! zjkIJHwU(nUD^FNI7CX^!CN0Xf(2S^YEHh`aD*^uc%kZazRuW0_xl046EsJi~*>J&1 zOmGtzvn@kG6iKDjV6fQ)IQ#8Q&akkzhrtFuAKMJRS8c79tqF72b%6LbS1FoB25_ou zIQ(EvvfYl{-lQ0H?iUYR7o>WMZ0ox#;<-K7y{`2r8m%tfVc&g?)U_0`cO19cjQ8~! zgoYa~&cgNI%7~rpui0=$cGHumJMXx3gV??F!k}@xhvR}3$%KBE)yK%!Q$Tvw{g}n= z_SO3;3EW?f72kxS;q$c5r~Kt#6{)6(Tq#ohJtSuU1L;NZ{kL~ZRd^b9X;Du=5RreT z5OI)e(ojn<@g=X1F}WvLS8DDHL!=n=J>_%KN0{TS#oxDi*P1TQxwoAwtOrm*No+Fu zX#5w#1*jQ%z8TH_LJ{OA!L8LD^RQ!mi~8MQ4_PTW6ID`FJ5?+&mHM^HG5Z^{SGAeZ z&mmHun;J=^)YQ4XrPQYp0j|PF52srK-A1406v5V>^>S4S^)j8?US}Ad2!tR~m28&e zXD=#jhWhk#hp+go6jhB%eQi!wz=6HX3w) z$^^AP$IfBU$(C}M0?>bTZ=luzHQ-&rKBVGndeV^yDqkpjP`O#vL-B{)M4f4Z? z>Vc}}=k)qU%OjD;OFQ-6BU~L=iEoQTMPv1@oq)(#C>?P1*EJ*#SE=W1d^)#a8QItO zW@OBy4a%QH^~NX;SfzTrPw`yNlb^F{BPAZ?G(@%teGed;L)`fSz2z^9Vo)$h60oy9 z+?-a0MX~HK^ZHAiA6f`LW=$|QOA&SdpasL^ZiDq6JDJ>(V1K_k9^xZ9Up&7|B5^o{ zk8D#3Q%w|fNWH9<`Q!JipEpd|m`=BQdFo<35hzxpncGu-@-u->twe&uz#(e9Mihr+ z)4gfH4=KnEwt*TNL|CLLb0kkbo7RtKy4@7qVdP;pv1RoN!Nki`D5g}v)M2swsG^luwZnR*3B17=4T+>N$c*A)?Ind?{1<;6Ft zEP6$kKtkh68~Gzg&HY-2Qv+)gj*BFrK z5}Yq@cxP!Z9#g!$^{}wzc3;!kzTwJXQPSS}gy?Iy$b9UBWNnykf_au64B0Gp{QI4K zc(m%g3cDo&mGVB8a|X8QLavhzY@&m=Jr)Xz;YY!ya{JBg%;Mne9k=_99&5_VYK|gO zqN38?KJwg840?vXCHA~zjLGm7y1%PtF?A(bC(+_Z%tC?rZWq+c7)*cFZ+)W9iVOXQ zN@z0LvILVPa-HN5Ab-WxlL#AC+2$)A#!|@Z`Ca2NS&jb&H?Fth)x)7cah4)8p->7V zUI7$rlUgV!M^rfmH-Wf*^<(eq8;b}>30WZt2DjS>(+2^QaGSzHhi&)s{c-315fE?Y z<6HD_n-){O#)tGWDoL%)*?zS}n>fL@nm=-yvL?20Kh!v#3F8^hA`SdXC_PF>w4H4j zww>xDv3>Y<{cA?RjtA$@ExBqqGzI^XtoZ6?;esXjLNnpIXx>?D|F>+~j}a{&TccFf zB+tspP#4ETP089pCwluW!Rqhii53IArUNN!&pSW1*2Nvr>!fURN?8WNo#{TXQ5rq- z7kv>HccZ7ZfvM~Jb=u3Xq-8yLH4D-3$6|w=BlGPETGm6?c^K|}_Pgh!4Q2QOS8hTX zpPX>RRK$gI3B)|th2Ovtj#Z9Yb1c3NXK+JCGsmOUKUBX;&&;4lwr#J}u6$S-><)ls zq>rhMI7WSZb{vgA%021r>LY~1?z!*rbebR$-@J=b05^4kp)>={HIg?K5!*|^`{28G zTqF%Fo~5xc_~&-twE|Ws0#17(BqnI*}$?0S@hQ8^W7Hk9UyG{pML9@|icY$|k8_1WTItM?;ci(0%BM%-AaCOU(apLsFQl|MVepf*EZ5c~Y|a1#j$jIyKI z`V?@mm~!Ff30G#IARao-@V2}b{WQv(DkMUS&Q30JhWB{2%ibZ7=w~zYK{51>LWlXD zb5RPb*$F22KXuu7(GKItAZpUzG{&(IwnV=~ytKf}k{t?2;gsv}`{N-Joz>&L6~hM4 zJwmLMQGRsf)jCM;*VIZXZ!r7ES&c*ELOk&*C#;2!3A%|+XuAL17b>ej1aBPJk2lJsa_ zUBwpUcWOV9e?-iVhO;f1QEyf?3#ajT(7%^B-E57J11pC>8I9#?Ft~HsoW5xv=?J~J ziPiVwZI{p3jhYDMCxJ7EtDU8NN;f1v!YDqlFrgv*&e6E6knHB>Uh+i-Qti3!J+YXnQeYi$p$14YO< zPCFAC6dpI>FtOi8uv4EX!jNJ;560G?ky?r;rx=^H56~$y8>aLU+|w2sCq)H5GB(kd zZii6nNc6)`8pmK?+y`kQue4GA#|z09a8$BuOTYoBdW9gETX%YBKvrla3t8e# zE6&0Gu#~%{*|CRdNzy2!y7xu&yv35($Z22kTBXeWVuH z)ef&(x!{k(3(CQsJ-N24SD&ig?Mkrc`ezx<;@T1TWhw2xP`o!avc64Ux%r4k{PnP| zsn5LI=q9Oow3Q8SFY##vCDG7(2Q}t5^crjkH6em%7-8TnyXhDk6bA2m+4kU}?iG*H zUaPV%0?wkGd@0RT3lAB1?sJ-veUWI&4a3D=LlB1FdBLu%;h?ZD9$P3n`*$1p$7(Qz29>0|H}eyHl%oQv5VSpHsI)Jz@kGe z11ItTbm6igWWLijeU?|&@!4qgk_bXF3}i3O(5?NB8%&2V;LU;)ichH1Z z3iprqA92c^CKW%)d`utuOyqu%BWWWIGFC)4&}n4-9z17Tb*dd9@Hs1l>E7GvISPK> zPd7a75n@uUFc~eAP=kinrSQ20(oQSM2v^k}SpMqn(XLzLPM;{Z1o?)Bj)I;gvVHyx z%KNd{`^o@Y(X8Dp=!;Ep!vd#to2*h~uFB_Y#7|_d$+g`3owZ5N z#xea0(tC~96^if^dQ=@Idv+EgN>KV?7`m=msI_ZsakyO4`qHv!x6RDq&3h#_{KBu1f5v#=5^iWxJhePxcKCL2gGV}Cs|B(jg`~%{?J?fQ~Foa~3E%bof zwXgEt#DOF>bycg`d%d6lW*sr1C&@(Au)N$RN&S&e>Hd59dU?N5!FJBJWF1cvn_a}7 z>-oc_4>z855Sz_!5zr5hS3AzG0_^Uip?%Ff?O2R|@KbnNT6YXfu~0J?6M7Rt&!ajz zUw-r{0Jn}w@B_~Vj)|=18znN8H_+YIevV~&hUGniCWYu23+{diRB*s;ym!q()Pqia z__OaK$$ENUdQLs^Sa^UE+0=Mr*OT2h5}$W+uHaWTt=T9^;W+IR9M(ypYc$Pm@$}Xt z9kE#W@d+7Lzcta~G6e^PG3?tWIF18}8_%9Be6kRv9DC`Q$(&vPYvgMGQVsO{%^luH zA7O}w1jTx>Q?`rHT_IRo0=bWRK25kmxUT?MBxEOc~MYY((DoIk$eV<%UG$4zSQPTrV0;IUv}S$vYl-78KiT{a~=#_?udgKf%^CZgiB2QMu<=E4#NKORYF$l zF-A20D^oI+f7R-33jeCr-&zosZlk|K5u)o)5=?z-%3^29TGT4l$b7NFM0_bvxyQ1O z*bSYgCpv`#s8dyf6Vn%oUg~pA_n zY?ht3@8d|wTW&NAr}qQz!b3E^!sWOLe))7gxAu>vXdx~=H*c~}HX{|iYS}YnzbBiT zoI^W%C=c4~JL0(v7s}u9-n$B*97^HoI*s?rzBua5)GPk4wL)nje^f{eDvqp)CfGgP zeb@}QN`<0{W-^vW0k)`Fi2b=$f!3$Imt8ypeu2SPjTPa27Pf9<9r zVl$=v9G|V0c6zo`gvx)p&?T6;Dh|>C`MayRj1EZIcKxu&c99eK%Aa7j%}P6Zk9d{0 zm|isk}@M*d}(8B;>0>l3184D)c*s?v;km z)2FOwk(Vr%Kz&vYKwnv>#8>msZIsxvWbN3_81(B@c0^Z{RHZrd*ojl&2m8oNSZ&S$ zSBdBkoTl1)+`P~Ynqsh$dmWk!fOKG(mkPJIyO>r=NZmePvimCz9@?p=%f+DDto!rO zgm!D8z%vy`&v&MLjek(D)h@4Cr|7K}@wCbLkSSDCv@M&p(6*DyJr)S~pSii0m-&N2 z$g+<<-|6S{Y#pXoySs{%c`4h+D?$daxlEE9+H`CjhnNDxMl~d`D!(@YV2b+? z*_YL>C^U`%o86}TaceDvV`r57iuNYz+yzykDb@&c*>q;}y9!p%Jh4BCy(^b%%rpTr zU3{Zk#Gstc7xiESnq(N|)aHo93GVD*8yAY5Q8dm~XG9+~BX3$6stTxGvHEQBAkGyF z2KRsK=z=Nw(vt#(a^o&*;a&3vkVZA{0H7SO%kS3HGoo88@{(nn5v*#fia1aGVil(P zB`;h$Egwc9`|v+eRsm9_{?ZA^aExEentyv3l{tQsAF`gy=Cm}R#$IJ^Wp@F53YD)Z zXVQEt3VkJbo`*U^O>9fniYT;Y#H{fr6WTju$rAySqGR%ukDy*MS5(5e;`d&~_IP*6 zUI{CW1pDTUf^4%v-)Rq%W5&#idB}fqM(qBvhe$t~PfH&s%+s_ataXoYfMa>w z8bsn==WpVBWI5*Y(M(1l6 zj7Br57zN{c`@k3Ve3?~~pKLT;G@cj(*lJu4mCJ%uf-z-K4!rCll_H#m{7Hf%*n@2a zX{6C)*#yChCl?<9%1<^$xU6^{l@BHF09DkcM}9sy|N5!skiFPB~2T4foaI7JcJ zjM!}0vV>Om5W_nK#f?r#vg>NWw6bt>m`0mki|0>J+)zG>ag=r0&0@mK$lA*tWx%GV z`}2Xn0g&`Vty*;)S*brCx~Djd=;*+ zL1e!8-%;qW{qYoGSLCw^ez1QT$*y%ydZd>v7!Ve?|cVDc;2T z-In@_z}E?p1DoDF^G zIcgSk%NB5mefV1XEg~4&=4AJW+Qd*84zMVmK-xk)U`Y%|%Q2)*eAmAIu>iR@hhS7Lrf9QaN<*SHbe18d_ zTxyXhoK2!-kW;QT9Q;D$$K{h=^{@Kn+3UHt%w(Ez`yo3C0;WjkhJxjw z8ebkQB|T%Gw^8ZKZk%)RiG_i6QRy|;Sbhy(i8i1~5_Pu^u3_f@&kThr!k&6V!BU@L zg&0YR_tEy70fPY|WvMf&*w_zb{?9OzdisoZ9jDHH-5CVOj4^nxWXnG>S1M=bMGK9QMXboOe3g0jM6atCciCE zM^pgo!DvU8BSvOQmTVu`2EvI3GYUrB>ej>VK)`DY9hl6!=0Li}uG+I!$B?uy<=or! zBaY&WEs_@cE`IZk&T=smSP7tzMnIP5>;($%wbD)+=NG?$S#`6sdld$%TPxQ93T!pe zDzy}te%s^zR6Ez@pQR~oqunBIt4}6sT?@PyzERM_8Gys*T`uIz&p-cy{nj30^S}lv zSwmRY`QdD&A&95-&lyp$>?*yOVBL$And_uquSc5YcxdULtzfAngi77?Urd93MMxY! z!JJ1-*z_Oy8?ESW;_PO=l9!w-xVAj$9i`ovEj86ar+JX^-z*eQ~;^FvcCCU&f7Z}*Ml*TTF`#+nG((}bs zLYe^tYptEH-VZam`F9$E%Ov5cgoF;j}SlBDm+UP8cWi zlb|6ZP2~@y3_tqBc0N1Z z+45+1E>QAa|78&=z6$7TmrljkI^f7weE~k&!BzSzMnqLmRQdKqJY?k$Rd5P;Slrr4 zv*X64_erZDCoToR+aQovSz+8HfR+YRWXKoE56;8ycnydP<9Mes;AKE_yLIj=LQggT zr%;w56I4q{z>`d-D)foFW{$LK@Agnz4G-XBzw@%t&_Nex?f_2S8|UR+eJFOaT6W=B z)qih1(c zBiHIS8q2UQUmd4(l}*}|(=#~vryJ$9dPO(3vQeeT@2DeArs zt#0QU*Hs!npAOsye3ik)`PqaM?%;bc&e(i_rJo2!pS7OdvC&-?OU7B^xf#=@N%9$Z z-gz9vMaK)uAuSykmtIM8NCV(lhQl*{e%I4S{>)M$s}g%TfJ^-2{rxbG7x*h{cl=pM z{cbX0BjKAK5sYZmC7Mo7I4v$MI0QI6lAE+L(U#D9p z2{IHGk@sq8sT#0p!QGz^)GWzSAm?$umVRGw;^zdAR6@gmw3(sSFEuC`msiF^a$d3< zEr)pH1r&q*_=k*s;N=09d+4aO+-__zLTCoIxEq?@f=xQt1j>)AwcLs(?X}Dgs6bs} zjZqNJ23|rDK1^HzRr_olW0-nxJl9(J57n{xbUIbDJUM@K-F2OMGjzDL5e{!CiHWU>D`lW3bbeMtam9gZ9#n^0JL{h zK(>kRPmy&?seS=0o%6F|jIVQh^AGb6rb}Nw;QK@ykU(r0eRSMG32P#hB{iKpbkQm{nZU~glED6nG$q(H zF8cC5kWoO3ve(X0oRHbx8zINcTkhkIA5`^nOYqBWhCZOZ+LLFGf#wP$B6PvdHEVsz zv9$?~GK?>#Y!@Tah*!hVhE6kQx`a@UaF*z8uHowW`7iT%T!2|)?+S;`(^J-D*Gouw-RmGhhjD3 zGFQ3ND{y-9%WK26g*67QEUe=Enp?#@Hb4??x(DN-F4sS&qcyS5JLLUEq})Zc`l@Aw zdOb0^|1ymnBRESs(wsqhtT${D-NNJSdcl!c_YQ14TA-@R3Qd1Z#qp-ud{QY@kss`LtUD`%RgQ(5pSb0yrWirghzM_WQh!G9y_;i(&$FtO&Zz83$eLC`I#LA$7wyby zskT5jvL%VXNr6I>PD={Jv&zMQ-Hc^Lwq>LwKl~zWkeGR0p{!1e1F^|4wc~d(Us&)? z3e3`;2c8voIaN4^xc4hlg3%2Al%FYmHCc%Z&{Vl2c1mG!2hfRDkr0&wV4j_W=$$3M zZAOYLv%1^UJAQ>Lwmtsg|9yJ@or67aH0EeHu2-~BgV@=H&on?`f<-W~eA!Op>|6;v z>Q}B*p)II41k74+SkOYtivVPExw1L^`N-94ts;Q{=JkbtNC>I*YvYFv07P*v+UU{z zPcP1(gDP;+28qRY)xCi9XdEG%NF4jYu*&{<_ybi6j4_ZR(Xg_9Xi10e>YYxh&9rD3 zV+gQ@)GW6IWy9Z-mc8*shmne_r=ojz&Mx-qwrk+s=Riqzhd5+GOjOVD9y~q`Q%&6> zY4iUk%gZ7n+==6eR)0U4uy;$D5(T~LRiN=`3*jU#SjeTDDYX<)f6Es-kU&7m?P7K0 zh*rZWyAzDvN&y`=Ml8Dex=W$gD)m(ZyoCq$EdZu`K)}9n5VGpXpPz*>0j4X=$nb1P zc!n7>8y{%V%ZJ<2vbO5Yyfck4(8i7nhk&%y@!jPWBC8wbSTn2;EvGyTNqlNIQCmTV zO7t~NgwNP^VA3F=rl<==uo%o2=6o5pFBWGw+M{Vyo(qLo5RG}R6p?M?oK@YB*m<-X zs4f?ub}v3tcCY;AgJ_JIM&pq0$QMAZOH%P4gqqfY+{#^thV&xx3i#&QzcJ~Pibd79 zQ%OaP%d#eboQyT|3F-C!PW=HO-@0SKtEA={ zKLfS^@@=?jI^7U@XPAu=!Ab}$q5d|%CYu?l`o&9`oy;(9r}zqx1r)|2eZ_)keXE_* zB|sP`@;y85b3#{7r!N8NE7$DCk2})PT#0My#1kQ1XBa>IZ;;ON#?KAEp9FHWVQSVh zpvSJeT!n}C74TcnMAExzK(bg$fsz=cIU=C&kj+0-#~kR4YlWZj!KpNae`e1j#EL)A z<8ECN#p_-a4$X#d?_F#)NZ(+!RbU`nG2{ip?{~{xw;kKkB`9k z+WwywA?^ArPJ z=I6egTcvt8dxIR*B(`5|r>jpy%lKWg2Nn9yZ9S*jpB0Q1obsFrS#n4B^>mqPg(a}* zd+5AJ5gy1`wUzsCbl$U)zy`QHaDYls%&_F4KLK`5EFpGsSl34!Tn~snM5+{a2n#kJ z;8m=VSPL$P_f$!$HSUmn*RPew`N-r~tUgw0SLD9&Yvggp2|X$uP)7pRKUt5i%4JC^ z*WAQBEg3xRDN+j-c3*-^RfC2x-|!T#r1c%hbq6t-;JkKS*UV53XV8CwBU?6T$U2!7 z8#4yc!Bd4tf$B(~=lJ?MvA7Y-*VM2%V~B2v{M0j;eq=`+9?KePZ%XegRA3Eo9Q&s+ zck;@quT7k@SG+xf1+$iIJyl=~ROc=IdG*;S^x_@E|KOYs|hpqn2#H5^zj-4s1iZP4G5_^ zm2J!P7cXU%`!ic_@QpzoXIY(}^cPuWjPr~13+B6==B5aft6|X={O1NbELtp$W@``1 z`5(l1NQe4b>A#R)v{JKz6eOGIrzXmX&K!^V_fX`o!BDIZE9%3xp9Y~{3z|&)3*M!} z?qCQ0IPkp9>^bQ z_P@OLT86mvXlHQ@!z*nxK^KihpnAkKK8Vh~x%>K~OeAW*pgQ>+}&G1Ld%!ZwVnQtz7} z5aZW~0}W$kFLzz_q_N94xynHUn-Rdao2`7P`w&ho{2kMQ!g`SXKbDpOv$Q&SocP;M z73KoJ0-1>=0J|zM)hH7=m~A2d)9-Ddgt7#EJ5X5N0wBaIF&+qXzz{m3f9HXEOuNWn zV508%mbvJ1?z{0x1PY*ksr=yB5wz9H{bN50VAEx5_Q0X7haZFHidFE(&76hliC@!f zgs2EXKW`^>nWkwyXhe9aXs$%afvD>Pa<~1+a};b^w5{(BFly*8e((H&zBhp_y&MGN`Y`;3`B7|Q}3<7lLOzAwMCqMp!GHf^_??4URpWGxf*v8#>XwDMt_RGV{3K0ztJ=4>@{4YuZg|Rynr@(IEAG5=OZn?RpVA6Qc z-6uI(h85P9f|K557+8n+7uY-p5U7gCL@_?pkQpOsAOBElKT$g}Txu~fi9vYREpQXj z>c3}IZ-oA_!M0?~F?4$1Gm0Pp=X3bqhl(-q&xItPQ6!RlK2>YtU-N-v)BP|OfK@PW z9E&-K^;-bA{MYGGWClkUVTmoV_8K1Qq?T|0kI_g0ACT!cu+80rIf%cWy9WH@1Y-U; z0j&RZCjkBN0{{Ox0qBnxz&HUUaxPp~@E@9p4-a$H$TookQjhi0bS3+jo%my8{K=KV zcy|rVs%&=@Q2j$SCH^@`c!$6NvG$1n51)XA83|jbw~iIFDju@~M1Pm@^*ykR5Pc60 z=Gp(#mdMgY;@H=3$*)Y*Rqbs|PWFi(7^&a|0~0hXHfbmX@yG4c70S8Nt4G}iC{{_M zxPpIHKeYMuXr~C+hfamHwxRPEe!Ia!{Ynff4KN|Q?r5gg15FmT46C>oA$CdEqdPfTFKUed{^HVj}y zL&{I*@{9hi2%HqF5VcBgk)UVf6QIdje)rn zH;Sxt{(g5HMnAIMETx#$FrLPeyazd>Af2%TqMUtD2MhzQ(jJz6h2YxoBy?d19JjOK zl0Hp=#=DmTP`-ArT``#bo*kwy1%p*ojytK00UE+C$*vMlFQCPgIZS;zu|W3k?&NAG^+wu z0Uuos*qCZP6b8b;u%S>RP>-Jgwf@>pzho6Hbo%YBpo4wgdTjydGBK&VI6o1^q6lO} zk_Vco-}-B6=~6hu%M#{oFt3F~D+~iNSnFyt2Fe&)&?WGv1vHLb8&%v5Dt9}e%-UbC z+ZY9YdBU&B`uleKBlz@dB;%aq_fNo$HsVkv!)w8rC{%$4t>r3Yn09393 z(yESIp`M?4JIPCSS3^B_zbUK%#NDxP06_I|{PyEQb+5$Mqv6|r*(!gjS~_B!tAy7d z`W)}_`ldqXM~=DM%C1?zKmnCl_6S5buHwA}cn^n(CHLPv019MiCjNi{T$I{D<{V+_29%D|HI@2%j@Yx~5vM5^br04iJY?8;(I z7Kl52*SL+IV8|pBhfsQ5nKfllP>~}^`?WLF0K2hZ^Ga)Rs6Ltp>=sfv-KL(C} zD-YzuPsrZzS%v}=`YazwV;94sRtbPPxw;l6BT@5$O;@NH3%7c$9X!ny?}z#i4*IXf zrjnQj6eHX8toP#k!>!`DR>_X?x%Xq?_!K#OWMDv{jryJO5vjtuD$rpg_qxcq&aIro zxTS(Ya|3XK#!x+lH{n8l+-HKv3WYWN9j=Z6zECIgHM8Q3?YoSALVHYA>P4cangWOe9;K z?vFY2E9^)0#K13szU7Y~xQdp0D!~Gwmzp;K(SWxK5YWL&J44{~++8^G-d>?^Chf}A zcsE|7u1tRkEB;k5W!sUlk{ah(Db+eg2VRs1Q2Pumd3yMLY|bD@0~d*^H2Jdm?jj16 zBx-L!_RZ~=s`cvqN(F)o3~jntsb|vb{{h6%fHQF1G6qahtaoF3AVr)^1<-T|#1t5p zQ9*sJVZFOno-@XgT}XlqkbO5T=6&Tff6XXM*)Xk(XZQKV^DJL<*16Oi?7>1a^PI=wQ4u~0;puB!ghjeuR z&AO=<1h&gR^Y&NE`VEF>f3Y-a#|N=}GQZoU1pqV-OfCGujuV>qEPzyM4laiFe+nrs zFYSQ+cVDE(lPTrsj$z$ zyLlX5xyGvC{X*zr+}bvVV=ihuUj8sw(%GQq3$*UJJKC>cXh0rdkrdpUe;|atJlRqj z;iLp5c6{=~x}3~IBnkZ0DXXre#e{w1(c?OhG^T8jN&a|%nYtui#xN0+cJ)t8xt|Rt zvZi~{Q99I8?Cdd%>04eWGVQfE|65>T%~I0qFj##f3atOIIKpf7J_w4$J>q0u!M`yVmE{^(Jz zvW`a|=-mg=Z@Ev#2n4L~9mE)D$hS9%s~D;xl{iv@9ep3zqgQ`~K@6e_@@LBE0Ahe` zfbD=MLj3FbED;soqhN7BGY$f78Pl9WM%_jSvAfV;gJZ7&!Cm=uYtUGf0?pH$WT#LJ zkrJoF^u&wf%kK-G&2BXmE339K3pN7qL4FEZJ^3$jvG$5_3vo=BMTvdS_H?Ou&C%kZ zzgoa;RnG>1No(MUR|1KvAvhj|%5m%&KMZPJ@-XevzkCji|8S@Sx~3J7PLaWlQvV2m z`T+-HGR5aJW~dMJ4oWa>`3DfCe=r6TWzcceX1Rp5=Wt1p>6sGu>_d>&bQ~F5bi8t0 z9Guqu34$*sU>lP!z9ga=1(fG%eBp3|cG=_mf0CdIP|}oot$-|`5|aafN_gC!KYj}I z*y6fF^(5auV7k(h0Q|jkFn!wEus_J$ekG=B3)O<-% zHT$XSl>XQNKyD^5;-{d*_DAjVu=oht41NZ)5jki%0i*<`6opDbMp%go(s5%$-qSl~ zl~u;e01eB$u`|y{Hh{c;f2)&rF?JGwXuqlB5ZXt|f!A>pmsMZQdxzA8>IF`iq@6ON zxA{ZkieYnqV9^|Q)-f^CF87N@kh}D?@LBf6#!*`%@boSz>Jb6DZlUlp#$kelqDMdc znJ+Z)td+=^n#x;Ub17Pd+p(8<&OgxK^168koC2dqEKl=2?mk;Hy*N(5lu7#lJgiy! zX=qy-2(-yfm^U=&=M10i0s)F4;I78cFle9a()V`o$_hK^bSucY-txvvuT3>!;84~8 zr0sq!0#x{;4Q=i~M&ot12Mw*|<)j+09n!5W2nDqgi+&zJ5a89lEm@^o7aCdtoLD7* zFDK_^+AP|L2Vd{XQYT}2i}bL$emv_r5bBzR_pz^(jIG3gmpkYfzfY1)e~v*wX9hHx ztW@YG&%7pm4r-W6F)H41_L&v`id+B~t4;yJhDN|{^llZz5pvOEfc89Cx6@NH@tCJz zN!8<%Rxb$%?)rpz;RBOO{4fBnR^0?k8D(fN!o4EE6!n$v2Qx%GL&2~DAp&e$P%S!R z;rs}M4{|OC9ip0_O@d_bak61xF@dA?vvIlG8jB#Yb&(TANc@Ca(0CtGjRGiM@l`tj z{^y{QNMN`bj}ble``f#eewC4GK^X7hv{g)T?1tm(Vo$3ihvBt7%=sTP`Qbya&iKc> zfiR&6L9>wy9MXdr(s3HggJm&n`F7Y_q6Hrs|W%Dm|*nnfK%#7zG zn7)iwG!G#xAR2tTs}&^|T+iKf>f|o0q6OYcQi4nC{Z-fuBvSU--oHE+Z`A=2tg${D z61~HPdIDOUInZChzOLY?>W9G(%(GE2M_O|N6%A#&D3gKa#VA6M1v%80>BkjnQh?CT@V?)VONcV9bZ4VjA|7AvnDr? z<$%i+U93mFFL8t86qQB7w~Gv|do3(oy8)x|%fxdjn_^+@qopE)<2k+=p0_16DwOyI48WA&y+%MtF0xCZKj5ln?2&o^V{4?LB-NV#!e` z=bg@1e4BDwvQ={kFq|vIpQ(kOO(~nhrkinTdgVDEOt%KyxjX-w1hTLZKrt|BfzE_X zID=XYY}E>({_P8tEi-}%b;_biP%dIyi;4+Kof#M0*?Uo(6qH~oBZ ze$Zrm1SBn$t{cB5+D)WZr=|1;>1Bm2-PtyuWetV9Z85dCcCHgKGrDn=1O#*kaz)9E*3qJ7)34VsPyF#`ZQ9XruN4Dj06l#?w-vhx!Zp zt&m520{j2P)_ccO`Nsd_5jlv?G0TW^?3HX%#zAJ1kdeLjDpI)7ku7^mWRJ3ES=pP) zE}ID1Bjk78y+5Dd_woBae*g984ClVC>%Ono^<1yf%WKWM{X!86eji+(Y<*pKME4*1}mC@bKX};e^oJI7IXCUZy9C$P~ zh&cb4PS&5W^m`_Yi=)OSdvGxeYCc`y3H#vE*X`ZSoW@CNicead-pZ*&kHm^!*qJv` z~2RHpB-H+X(FZs}jTSOkS1wAckPdbn6w_Vqtjl}0~#c5G?Z(;G)i(IAJ|Q+P3s zUqlrSv){amO-0Bb!Gs-``O}}sw(a(~U0R@g;D5|C_t}kfkWkW5cV~Ix^GNX3`HOkC z(enL0y;tTUE&Z$`T!WI9>(<9UWK7ZZ6MqkXn(%~^(lt`V&pOpQ=>zn9GJws$Wbt-G zaCLdFlW=Fo|PSD)SEC>N-Q@3wYw8zQ%z7B1FkY5ptB zL4?cVHt?j^?VA``r8x%_T8?zH4-c!E1jm0Jz~7l`zc0aBOd&q)8pB6POYTxUXy%F* z_*oWLnh?$w7$SBDdeGE^10goFZaoA&@)5?Dy>dBE||-b0e9)<88<<27Q`NP~!1Hyi0dMQ1FAt)^tiPWmCU8VkPD0l#33 ze0Ka;bsVzQuFZ*pf$B>-FUlmCMV_0h>LP*tefC^6ojoSV{^(R*yydk&7-bm&4kaVu zaC#3$pRE?60lj!yG(TgSIZ9I3K{@;kq%DaTkwt!JST7Hw?`3_Xnr03*6kVI%-Ycf< zqApS~O1hqixK5!kq*+=_K7T+eEjg2lw{A9h_To#D^D9P5>oHl4?c&9PpT>627^vLW z3FyCX*FoG&KJAYOP9vXI#Qo_}tR=XHmO3V+!6u~$Ordh=RS6UD)LwsNbx#*ZVyTZ2 z+uGgPLGKvP1&%S{&;0W^a9Ds6>L6Zyow@nNTp8BMcs%pUGr;M3V87-_w#NrX9B1&Q z-fW&HxH1`8DzkNSA{IDwKlTy~kiL29c1i3ITEHcB>(#H{AY@;UQ^zWrZG-n-<^g#(xwx@3d`Fclf zMK_DE^2(pm|H5Ql?wr|cyZV_Vep9HmqI)_ZN%H60muWdg<6J6d1`agJ{241a_ZFpc zLf%PRs!%)JRAUlOgTVKZV^m-Cp=K0`wMA?EA2)VEv_J*IPXQdr4NGv1$>vd<>!9j3HZYVjLE~N@waCqKY9wgpr7A!Mo{?@^)n;0EajxhbCz>3DzULi7k zSIEpu?k3;!17A(nkxM8&W~bRAkAR*%_yhJ8G9`{{OaaFc~88Tz=_yc z{ja~X1Y4+imUIaXDG2Lp{gNkq>e*8!&!2(7CaYapX z1F5q4*`u&30^@WoGh%YrR=lSOibfY#T*o6K)%&1E!v=qVEE+Xj9jqSV&rR#~s^913 ziTj@8C$98?ei?eU)%w)3axF zLDlA~J*>Fe8xMVuSOn{7;WOp3>F(!^nm6HExs>6haeEN)F5W+Pf%yz|%P^o_WfuAi5vSHh7vmk7FTI+&2mdS45RG`shCjX`)j`qI>1y0+!- zeKJB#y{<^+r=)H&4pH_2aq;~klOolERi!H;8K>M3HCD~z$Zhd6MO^>v@Ewc>-~+F3 zd6%~G6V3JZ#?)`&wF$-K=mez`C8C6}&En8qF_B;{HVMS6U_B9M;g z*hz8d^t024`@YorID~Nf?B|-h$^`O2W(|hO=Bv0nA1hAKo$G&p7j+oDK|=`REA6Oz zLbwH`cIwZEVQue!XoYjm++jl z9VPqT^J)mQz0aK`>g#~BR+e^SF&@;-?2v6-`~BY`>;o1p??87c2)lCPQShGD{}cvC zb{~aJyC)z+bCInotv95BwCJT43Z<*0`I|67D5R^;>2@3H(9GZT5$9k1Qzz>j$M!2DZlkWA(uS|Tf~H!@r_emo~AspT~(I&PI& zTQs+{FOC9xS z>ekWw2SgrB^Do*2ukUm7;Ce_aT0aGIBwUz~dC4NxVzQe~B0|3NJ@W1GzewqAFycT|79Z)Zxmi&$IL=v$@pr7x%jV%{Kb2kUat zM_$Z(*2DG~(GW%)A#*CW^Z9j1Eb+*dXv;@Vxi@(Th}q~Q{AD@Rl4jGkdOJ#cJFk-1 zGn7sxvndomVg0e*@8F|88QCdxSNp~fb$;5|}_=5t?_ z|IULS2!LBZ+Cp`1j@$Tw>&C6GO4nmUOK>+$6q)&ZcgQs@I~h}Ljx^K*m6|78?;yC^ zF5#1^qEyXsH=3WzGn6x%sxT`bfpT+B88PKw72=69)!MqI^4dHwzZ+hHke{x1vUtG- zydaUVg~YA1OtJzw3kfr}he^}~lnK1^8rw$l7bv`iX1I!7qbRU@^jU!rCHtjIygVcP z6WK9H?6HQ;MDr-@o#UZI*auLJ*-!+loZp>0Ewwq&Ftwu|73bu^X;yV6r?X)L7BHeA zy`8SYN7k-5^6kv=vmj_owLR+dM4F+GcrS=}vtr1n0yqCnJ_3UR{uj#eeocpKETUXe}Z;T;@FvxBg}2$n zI1$+d;WmVr(HZ^R0GG+PRyrb(5v0S!dz)91g8TxJXF`v-Bjn#kOpL>t)Kvn_pE@gQ zFa#%kO|p9%FBZu?YohT0T$er_PmTa`l(aN1iLI;z{F3s4k@cSo8qQfYlnH)vwcDAP zaZ7I3ILgQ^1}Bh3#?Ys%8zHVv)ag!~$r^d9N}0e6%Unz>$llLaXIBWRzV8(h6)$$x z_%Wher~xIkjC&onlJeIYmpx=ax0%jZr$0>~rH#5pO3~?=pyq0kh#V28#zS$^`IoYH zWr@fTK2nl7E5gI~FYS=E#3Fu?H=H7f{az#IuIS!kQDV2gU?zZ3r;=PB=c@&dlv^D3 z#OR2JU`(@6V0w7-92wI;H@K9nQE!-9n?jG~)3(>8vNy|zxAd8}4ix5`u z(*S#dN`nS1pu`u$WOOMl8rSl?-B|#p9AT`vd85h|2_HO*ZkAWxzpH%B+b#$ppYHdj zH~&z>Y5(E*atA+`XX2zd;y>(#ZK>daq{=IBkT4R|p!lk>?;LPTC@41$`hVZCbW`JL z5rXO^{Fd-P1%1BGAAVP zHd<7^a1Fi~ATVx4Xws{M%4A6SJidAgXq^PD2Gz{6G=hvP7gMWRDzh=Tc#xs-MxvCV?pOCYyd2UIco_! z>uw5|m3z$Tjh_K=vAt{tnY+vCN7sdIGz96gbr$6>Fg4qL$<+h45w{)=aM6qAjNWzshsb*j z6a^hZK>Sj(!g8Xt)XjAmeg~nEajBZwN(Ve+ME47e9dbDnt&WHu5;N!q^_F2SR`t&(cW$_%+kK zGZN0t8%jK4!|jY1_GkgM!&L%r_DZv__bo$Zq#$C3=RY&60gOHwA@(C_&@43O5LRpf z?OqiCQAPK5e3r?8kBzZO5NH|@K=+KJv8wA)CCHM2-Q|^l{}tz%2UATK$Q`H|1ajCU zf9(U)i!~tB5Nv~cYTnCa#F<0eJaXU`yh(hdW@DOA^iiIfn*fBdIdG&wE&*rYdf_bL z_DO3*##^BQ@z0}r){HNJnaBaKh=Zh78D2nA!f*Ii4UpWem|3CBK<(Tels_lM)te@M zD7`lsfHv}_D$+Gg|6k^610*hcNbe^9`{UjRxE&f0Ih_oCdxE=Zj|>4u9VV@AG$IqI zp@AI9U>$3Xd}Rs<%1AZJ<-v^Kt!@HMf3Y9WKEHxMv?H8O_H=W4f>2MvrMP~rkkA<cC|B&@dlsI4e-Q zK$C56`G#Tr*NzB!YmoK%{?qYt>H!2sN*@TL!^dS58K1@hmYaW1@TJvHA!lH!%PIT? zBp0FBW@{{u3ZZsBLO#414&2>s=m@{IF!15?hv4AdDW`^#u=(jyQ@JS+tMomFx}gTK z)9v2`3qNw+)WAt{jO%JHIvz!31aJ=OIG~vgD}RBpn^sWjgl2-=uN+R=^LyUV2l_k~ z+0WKLfZ9qvv48?x-x3N8y8HtI`PmGDao<5N4_JRjY7(3@hjyhfkz0~jUa%IQZz3+sQ{i2&nXsbw958LHZd#dqEw%d!r}4h>X%nc8jNpanRT3;n z3;9zpmx54oYwFM!JMdJ^|ClOlLa?U6i^YY??hSZ1kbA+OmC3JH`==EGchCG+jT|62 zlLzKHFdbA?KOXvkk023jRk?5-d{=%&u%j(%av(q|2KJ4N>*LRXug%<5p|F_Pu?Se;XxuetFXt`C~Ms@W`bXm!^P) z%X1j$an}I=ULAD(Ij6OQDbU}*SqsG6IBYIe0#YSCHO~EWMHdJgAhiKHM=S<}3{WUp zvf#V2Hroz;#7RC~+k3rc&UOnBts8)6aSP)8`^)&;ZS-BE&q@6ZngPyK_f**j2(l@h z!3^J3dQRdt+c4D%vT90e`CQ2iqw(T{_@I zYLE?U2A(U88!!n7TzCy%%02+*@X;9157)UJAHtY<&q`DmY$$R9BANKfm$kouM;VR} z=P5RZgDHaKcN!uYCFxe!$r!|k)Fn5BJ)a){gXua@tav!y`0cv}wL{d8t|q((>`T4J z4A2{Io)3yIT=rZOWk?ls-sE+3kpz5o`u+xZM7VhE{*FVg0S{@%NsP;zhYT54zSRkX zd5ym-T@;Urif#s*+_F&{P;Di{LAIms4JF|lzu^FW7zSip55B1eA-=Gxc>|D|o~=tD zRNWQQNdeh%`e2S705K+N(tLr#;UDGWwhu=bC5Ev3qlEX zDwFMzZirks0-6}Qop9cjA=(IHhu)tB(-HK5UC0KQKPrJ&>Brdy;2sB`L4XJ;0pvJL zt#kMy0~RX)kUkE?t>z1zuRWh09X6eBw9#xV3;za_Hj=&=;WBTnf`D5JEcgJC4tVsJ z^mw!Wua@8na6F&7XuroG>G5?rAefEkVAZ9AIeS=6JPLyIty`4%l)=P0!_uB9knT87 z&1T^NUZ}HMPQgL|c>}PUEuVJ#8BQQbb>hNUxrWrtLtQ#DFFw z1pW24ZV?A=+VuGR;;q>kt`&=fd|fLn!VrXM0Y(p&6UeLTS=%O*m&!*YF`&Id1?=Gm zQA13r!nQFL2af^OG=L8xV|A^}R)d$ynD<*0x#E#B|FpX=xbR+?$ksA{)V;)l_Tyw> z!Ugz^T53qs>BE=_Z$AOkK@vBg-FR5m1TR zVUEz{qTlf##-ten;Uu;ou04dJxwQf)8zz7`%anIJ>WA-%ROH!~iKintWcM<)G>=?0yKv5O>eoYpPRP%_mkKSP2Go0Otesld!h$|eEJENF z=dG>gi|K?U5GEmMi?Oxm^SL=&D-qEQJFjH&+Cv?LY5Xx*8|h0+uq{y45Ao><8mCR1 zalJ<&zw~2Ja28|o=KT=51d<}Hg877x$jC~fOT1^%$aq*+0-JQ-r+=kK!HV}WBYB8s zKdV1^lZWT7>XWX*2}~3%cyxQU6sjpOUnh9heYpCi^V6PJw0T5}=~bR90T;^rpP8(N zBuXTNmp4>u(x9t#j`#Bm1M~=GCOrGMY2+*xJ-DRzAJGHzb$N z7RttYnt&u0S2DkM43q%h1xMnz9ztm{=JVK(rvA!$<~<}8<=CHvMep5~=CvX+kV`v4 zhKL7JzKTa1rH@~kV4Ir@KAw~9=#^hYaC$Q~sS+Y%+*Ot|7Y)G@gS z$OsAlpbr2U`;ol)`L!~P7)gT|nw`(ub?}xMEF-!dHd2)F>kNg>EQG-B7Kdg=XQR>h zn5bv?btK7;f8W1tBBDWHrUv$bj`Y03u>afz;1~wS(1`ig8-TCG!bL1X+dv!au$&lR zN0iGOq%C`=Rrw$E!CnbNA7FpX`EMuY4n$>&hRTG)8^3^4ZXwV=BH>R#ptO|V>QMpT z=nZeUM>#x-U|$xe*!outjDIeyK*S;8{T5f6UjV+38q|THOc0I(8#V@P%h<3da#|AL zBLSdR`Ts5Tkp7GRy%aNcZWoPU4TVdK{8vQ+;M?>d%733K?|7b+po{SpQ0v!3tKc91NgTRs&>1BKH}lZ$>DEjkVpJp zGT!%iXGs(+`d{CQ5`m+9@J8)yfYLX;c(@j!0Z%`h{UAG#88j zlTKwZurG|hQ@jFnyT2$#^+goHa5{j6Y)Yx^3$Buo%}*PIuRpJTwmnb1^d1P)4#3BH z=(L93KpLhP(eSUC=>$M3^T~v8V+lx9O@MG%)OB9|1lUP7z>lrI zCS)}ZfE}N zql{>O8>^)NCM%SfIRLm8tl^{RKFAln8woLR31rJszQ70VI6~k~F9*P4Jq45@j__6r z*BTkH59iwl;~6-zfa5t*I+(c)nT2rO1A^%(5Ww#YAJt%o6G&c}21?!OFW})MZT}@V z0``NKt;E@1WW~9$<)47{6{^C_7N9wwx84+{FF}0+{|x~ICWGe%$aVRb=#jMyyK`V~ z6wr5n&`9vs!(JD%3XiycXVU1|93jV>zxyAc383+?2UX)vv7_LPM5M}H=|XCZMhrm@ z4;BaLNFD*oO1w^+3j!Bak3>zet7mIeIDY+B@Kh1RHn8p=;J@bG!;U zabRr~)O^!HDSB2ci3frq z%E4BYZ;_A)x)q2nYL$YOQVo*Y(%z0)8eI9#fj>dfym~F88dg%nmXsP{>iD*iX&`un zb*z`5=Ua0HYNfs^n*A0uC@0pj$)j(oGMa!1%v^UljD(RedYO z#pm<}8Cvtk!YTG(an!K6B?8k*zTDm95a=Jc^siOQ?zbCD26O}&t5dF9&maz0l*L@Up$2#0Sc^5PaK!1!}v|wF+Y?0Aen-Pf}Gmmnm;V>H!*6f z`U&=2c>TwJ&uR*j0pT_@{H8034;P-e&l8tYzhN{LXZ`>*g_$*;b6HL6u^}^)No5%m z#WPk@ZyKDfA)@uEuXbPauRqtbP-4I^G)(AqB%H8jXOU)t)ian*_5`#|sOu_ymPg6< z5V*^Ob$XnL0>-`rh+)$q5A+>Ss3Z7utXizkFUc^ur4Zz4vD4CEt;IG$j^Pw$G3swMFgY4a zte={`HpUZ|G61K`w~u-OoWR|ZbI|@Z`CwGi_-d~?DedVaIG3XfnAON63%|S>_0GEs zV8f%xFRLZ(f}op6j4ppHwE_YvW9Z0q;Vt20dwBr}$N%Jkl&C#x0fPrNu9`o0Lc4V= zS28Z>?C>`pwZbWfAE~Ro>n7GEpz*K|_bQp7l!YE;TI}hIuzs=1*hpu`UmqS#JsVyT zf>R=^fud&omIm!(#N5^IptV-2luv!a=N$<_(loJN*e6m6n#MpH*x~m zN8M4tJnWROX4(uuSN&n;PeKI*UP_%V+MmoW6oB3*JK@-TyKmecTeAHdv!jwz;Bb>L zw%Oue4;o~63`nfBx!L=)1R@`B)AH#r1}Jl}gw&5hFDdFy1l(_ z@J_nRWe8{?Hh}l8-}6D{vat(VejSf5EO0U?x|_G^_T9eAY$${Zv)w$4-9B;8gE8vY z7p#Nk4g|c9wmv?Z-{rTSB>fP{5xl3u6^oq5H`>Wd|JtE1I>Y_@={vuHbV*6*FjzeO zo{kH8@u7+A^Lv3fIR1)zpv{^_dl#zywMql3E)V>G=hCJVJ$;l@5If2i{QUbEkE}hY`@{Q zUAx&5#{ou=a`~~kMR~*7fj24 zbFF*j6C0Xp|3|pYnfE0vg2EzhDu0>jHihXm1KbV13Ctll_jqRAwsu|;LfzaxPLwM9 z4ITNg5v}eC0zRRyKcdFgBrju{-FYP{XDq1Vn|Q%rfHm}Sq-g9McsT>hN5JigFI?uQXKxH=3rCUOX|{so3aK3gZt` zu_@2rxz%fh$7JP7UZ649y9yFleV@44!56Bq@9tW3{qg1eU@g6GoJjxLu#noZCYkS# z1>0xo+sd!dWP0ajKDzVPbMKu*z7rwE;+cW+&8Ud%kI7 z<1lyJ+PJT@DUr9Nw3rzid|Bs%&Nuyy>U2impPQg@-?troNYEJ62Zj!HcOxLWrBB5U zq+9UFSgO|HHg~USu;FsDQ&WVuqbd*L_GbIaw_(=_ihlzn<_-u3nbh1%{_`%v>yR{6 z(pfe~3^ekv0NE~lk~^h$999@>iiKw$^NRz3HsZ+tW|-X${LKngv@BZu8F-{&kCGxy?yej?;e#V{XsEBS13l|uBV zvt5oAP6!pri?p=L4x!G4%mgwzUzTBG5_EN1Fq_N_-HB$ueD2?(gDHBbZ>DOgw1 zWRIXX#&vgIT-!{qt8qTucrviN6+ZCf(W549!~M~aE4P_{jeYR^##?RnjXn8q|A%tB z{sacbZ1aX>Zj@QcdxO04J@J~VuSE~Lzo9#B>%4y~0jIz{_KE!7@o=Ih4l$u1fj!I- z%$yDgL=dh`JN)>lw*v|Ype2q1h$5Y2RVw5*+lK{41slDY}QvB^j}iQvhTdQn&Wku9)s-f&oVVk5~8?+~l-P0U#4 zkG)9bCKjSsnxlfN?X={(5g{| zZZsy0h`5umr?8$@vkM-5gGfr8Zy06bT3)T%(aHrw{QokN@Q}#r>_uQP;d%pM6 zG;Nm`aCl7)6XossR?zVhEjX&#t0^o4fqWOJDLFt{TzIVb=`Bd@=mGe=#nx<#8+iJ4 z0pyJjz__s>b5qgd_YXceQiQ8CcytxW`V%k;p-PS3(6L%$cuzc!wJi?r5V$)Nb#v1T z^s>wWE?UiM2fd1`Z&A+yo3scD!bISrB@O!p{oQ5q0$DMAwiV#OgtgM4K~|~|UAZoN z29&`s0v)P-AMxr~2&`b^tRZ43?{w!rkFdDgS2@Nbj^ zB?R$&bl_2XR1DzT;oR9Y+WW9mvr8FxGB0z%2=Nl&7~%i`+XMJTE5Y`i6L4ZO1|*Gh zr7AE;MuRKtW`dwoQ#+DOx(~)pjT%qu!4li~0G+9VAg>$m6kkgPAY{8ht0qoh*%0JV z(%fDd%$Pxfp#SGxtmZEn0CFd9H(G4#t5d8ytX2L>X_!N>Le%-kV{j*MfpD*A;9jW3 zGt_tFCO)E%j#_j1<- zorya0nr)WJ2G0yI>-P@UC#=bz2a?jpQM9Aw3ElcJhNULHt51y#Y<+eFVx*0Y@{Ic{ zJN3tb5w;F!#0+hv)9?Pf19M(Jk>9*$iLJv^29@Gv)Gg4s>b1?Ac6>7ONwn}yB`8NF z9>*C4T*JCU^KTvJen%w&4yZRtz!=(QW|fYPjpjZ5|wR=_G}sd(^tr{yPdK1RXn|fcczs4Q>fb_=IP;NK5z%zz3#L3 zATLw3;gi+@9~;*8GvnV&n#meYZ~bl8fgMkDnO{}+Hk@Vo5c++|%%8GK0jK+QX#H&g zdXAQkHdq6|;eCo>4wIG2aMW|3F*xnU0Q{nxOl&$z0mm!=OnQmnFvTc~+d8ZRG+IS4 z(orT9&;TBC^|eHra>9h%8@d>Rf`D2;!>NZ-^DJL_Y+F;1>g$c5POQvJ;HQ6E+yO^P zHbR~pmWP`@g7yQLmK4jg){j@V1?Vye=JrB@qrNfA=Re!VXy$9kQp(4qBe&1f z2OPMq(>$`Mc$Pmd>;Zt>xpLW;w6`oi!)4;a8I1iVbETc@dCBT(Eg0Pm^_+KO5N zi1==aB#@WM#U)7}G2Q_vvEYjX2f4U%dz`ND@D0;}R^eCY6w=#5Fcpi&BKehu!GRtP zXvmw5cd6Xk)?am#J5v8u0of9XurKEELV}C_JLhikfZXy4q1OV$Q27PxL|~#NW>>AW zfNjdhLXq({KemcU3bO-Vr~XD{egN1KO@c!)(!L|*H`=iK`h_ikyI$S+3H)p~0QMo$ z|1M(5V2-{_iQuoxVnPU+*%82NvH_GFupE04F*&G4v)FY7{V=!o z@kriFhA(gRr=3O8J*^@>t`!#b>92|@Th5RWqUPmTcsLJK*y*Lv>cozn20y>pW{^co znQbcTO#f6YA5^!*vQ1ePj+Nn|q+Z*S_Fu6Ga`8~pfR4@|gIdTc4XBh>O&V3?am@F{ z6)IfUr)uuQ7{J0Kc`Z5|0U70BGjUX)lq4$P$vX;Pz&D3qK{hHZGW!RA;ZMt~yOJf> zN$9fh|wA5kq>?3U$pK4clBJB zh}HdhgNYi?jP>a{gKFm~u9E|3NzISfA%+cGhRb)E!*(Ph+;Dg4)>Gf;K6<`y!(pjH zt7>z%Lg>2p$q@o19`y}uy#EmkmO2Tht#uC=!w?)kQYw}B32I3n-6b#5oBgjqaVX0D_Wcz1X^<1=1cC5V>V0qOGBDB{oP zXAKm>6yvVXNTkw2lXrxl+3*Zq$Z|B_ZTZ^0>*ZYO9`#@pPuL$^awwnCM_qsbB)Vye zOFom3xW9lxPj<3~Enix9>9Y1Q>mwGI`GrUPns%bAK8}-uqFC8Lwn5%h&~xag%T<}1 z5xVv_esSB=*)y5<(ft8PCOscD-D7f2kozf2L_mHqobfl*>VIK(4$B&BN?nI19`7)~^ zC-cbubT*e>&5SmAuxvpP>ok%bLj1eK!jC54Ab%<56H{b=6cxRSB{pZg(&!DEAlU3P zufNQ!IWa2o$B`*~Xy;;!>y1D}ClcO6>E9xVfQDeT%d$u|;S8@@FmF~8UC4-BuRqtz z&m_v670^Y8c?R8l*S3!Kj^3L7!?qVLZ(Ev3zg%9t!pHDC)cuxx*vgkHjf$iAqB4#5 z$=SUt3W5_YIIp8X?f&|5cTVUndusV$fu%Dv14sIk7=eqOVGg+4?4h`}z7VdAD&qBI zNRd@2@Uos2N1thwZU=sa@FdIT=f%ET4z}8Q=U178vBhOJMgs0ai9eZwu)@Xas_MH; zW|t>aABEioq8y5eQrFb*YlrE)#*G6<7dC!;;;_WG_|#;GvDlPmjp2ukxO7YXsJL}y zfDs)tX7o*uTbp+wNhi3>^71w5CS~puNM|+#NqUtDNpMMo86B1HpeKVCO_M1m^J{+@ zOR;vFMj*{m&jF>?B2PF>9>zx+Y*|0wru0*kyc}^@j@){{VV6O6q1-ZEP?z&3Jx3+j z^j2Hu!dK7^bop)*%tOrW2cL^V5;!qv%Ck8OChBhC0UM&5IS$jc!$-T>`pT0K2AdFD zFQVS()A;V0eDLvW54^bx_z(OqZ2PDG?kM|Aj}C z%a#`vpj5_gpnNx(-)8-L&t{sBck%IStD%CYuRLh@j95N=x}z{!Jdvbj`Ymnwp1wS1 z?%YSO9i?^^OUs|L*WISeL>O7Hw=vYM(cR9h@xFv_5Sdnrgii4{OfYWq3J_UX0--b+ zjist?r9|1=dIi1#Wr{fhOT%6>)vF?njEFqTO1aT264H)UYHhcy1J_8)Xq*EYDcWbA zA7LJX%o9~t%1`8L`5XD=hCFXIQ*xSo*&tZ|Uf&dboCXl3$8yh*{36)0fsuqkB#OhE z=d_6}>Y8`ck&amtUgJFmNT|e(J?Z1t#5}#_!@$cj*;^B>{%=H+nvy;WL|52aA8MEX zYFOlmK+@5VV)03z8GFw*`&~3Be#;k1JAvQ|p(Q3BU=Y@;Va`jKp(P)QdX)BV_>T)C z9eT%I_B|Slc*cRj>acQ}uT(DzpQnFAFvd7ed3K+It~Lj+Nr4gsO6+a)IjCY&N1}I# z(}%L(S2~aBro7QLR*C0byNc3`(CF*icYD`1c!~Zdx<6sIG<4w!&=B+~4hHzS*a22H z0+}aHL-xy}8;d=v$U&L4_<|gpKA$u{aj)pB{5m&Zu-RoiykTeI>o%XsM-#R#kBC5W z#B48grskH#%i*A#v@(%qCvyj8(fL07onu9wZsvJU;mk{nmGqmhi8ci!%)KO@DWu&{%8{5lR**J`^XcCP8Wmd~v z6at+k#iXC|EIJ~p<5_eRl6(4+I45ZE>}*`|3UWiVNu-E|)S7KzS=#&sP^i|AR>x$f zDT^8^QFs<1zPq>cyq^~TT^2o0KS0gb9TArpG%5HRm8vx!Z_?^Dn!V&Jd3Z}c*!h!s ziHh4FTMjyWtsFPK1(}WP{MS)ef{}T5yaO~sI#Z}`%FeMghY&uzO3JJ5i)7ULaD>Rz zzY7tn(t9KFBaVG;V{jXc@jHMM?o;gP>?`;KM7e6?QiJmJ^3p?><~rMy;}sYwUah6H z2R6!;i!ZsQv}Y4Ze4as{u+J_MsOOY0Q=)@8{vr}q1(FX3N@VQTF&SzvjErLqzJ`Bm z(h@tI_QnmZ&8D{8@AARiyF5en7whnY0Wum|G;5SyuuDXkcCaPHwofQk71sBXX?zLp5uMW_W!yyoE3jf+~w`Dv#^A?;5*GAURORQ(fB9FKNnEQN=X}=BNNx<1*(_F zq%&F1Hss>ExWgfeYHu|Y@1IBXbI=z*_Ats@bt2+q=5#VuYR1g^ry9@|~RjDeD_o3Jf z`Y)gN3!9LMpU27hOm+RWT3g*Ed}lALkX?>{CDRpcrm79yW@lx&9WI2-PzIYhOV|o6!DdzdHR)~iG>2bE}!sJNFZnvAmXFB!}Ok+h?N>%E;Hr)w9 zwl*&HY%iR*3@#>FIf0VFVZ7Yh%mahPQHF~s-;AB3QY!zT#hQ2U(6)1M?2;i1j^z4C z4>8RKQvnU<(`Yq+t<#6hWl$H;A~~PlJc86`Y^aBs&D@%0g?Y15eNLmb9=8g9z5-pz z6H@*CqvC#Ja+QV(*hxA?irEQCPaPw(Hpe5=Uo4(50Y_J?ZyXtY^)iV~xje$`VJ7z4 zsuwsL&*YX-@#u*2sJ%h{{b1FX2;QQcIKY>!`(Q;-&E9I&4~d4xrK;WjW)7qIiP!W_ zUx97XoI#-b*UQ{jv785sTC5LF3M%Ig?O&?nZidZ<$&k|tL*mfw3h}u{Rw)VJ&#IA_E~%(ZfGC=c{^p_U}<5{H)_6} zM7hXnKSw{lTn|#v97a0+C^wY4F0I;_d~6??x!;XMSIRKnmwxbPZZ=oypptyj_x^F`kr4~@<5DwA8tYrY#i(M^)N)Fko!9Tz5>wo}EM zPBS`f@_r7Zv@!h?433L5f(iSqO#2o~4Ss?AZkdvPyEarJkab5bo3*7?grgwUgn6zZilJj0yfGAK`326Vv{bBHGf)014`8~f?xKy`*xJvyPEJ_%Ez z9;%aZ1wx?Q+=kvw>I{V-EfN=<5ajQ~7bw_b!T2()nv<4wP@w;&B3Q!^b3AuNw@Q`2 zD$9JGk#^XX_;FHt-9&&nrC&L-uOmFUDV6t2t!W(JLp61W$Es^z3z-#2X!}Nxrh=)0 zPv5Jh-Bzr2n(|6|1s>j+R75JFQekjpU^B?}TgO1>&p!@r~6wC~00n?a&{YuHOd$l=JV`*TQVj82oM0 zd4iV`u~)?5(M^53Wa`hlfuEv4QXHdpgIhlMFr52Z@Y;)$4f+9jD7cuVtD}3!M-6&d zH0Bh|^@TPmL+Q=!a}JTB#8^tYZ&9I3s>vg?h%u+>+Iv#zM=wu>oy$P8!ztWsCk0wq zCP$SzR)>#H<-_ijYT!;zMWw2w$9h5z^gdqMcp(0`=`=aVuu!`qYj5?N`qAo>uU9j7 z6y=M7YAq8+*?@{P!Z0iL{(FXz9+{}3-lk~pq51HfF7sU-;;^k-r zYgDG?y?cu)?+~)fX14qNtLC@pm$S^Px-pK*}Mf-x$%a=CO>5gfHOF^iq3J-rM7 zYDoR6_vn-*$ik9m?YtpZk7yQCcus|HGd`Y9)78B$p=z-?*lRKK_j83BlXh;Bu+;lk zU-O^G#c`c^c34-+Ez+l)onaw>x;U4=7;}=?#yw}JyX>~>Nw6oY*WeV^cfNl=`R_OH z*dk7yd_E5q03vs+a-{qe5hIva@zh8K{kRob*)Yku$_wh%4tG>sa^kN(0Sze`(3D#j^8Hp$BY>Lui4jp2m#bpi^PbvTkHVHRl^Dek1u? zmChJON#SUKI_HvOV?0f0SdIw#PPzX>$!~>9tvv#_pW^pX(3xCDw@Xg<$LFOva-ZF} zM_E#g!{$!i2_+2{f5e)4ve@jGWbg$)SCG>5aZvZf#}&r+c13PTT5b-iLSS81m0REU z#&5qP{#eZRvB7|JO+=hzA25MOGZ)X4-sx0a6o~vnWO-H}k;@RIJ-{`5 zPrHbLjn>d56p$tp+ZxBvxOGfe#P3(F^S%lHuu9+S${Bln@x)89H|)g(gJm?jOfu!Zlk-?N2LQu|x$y4bfWcTD8$bHL5t7Ati;O zKSe_P?uaPY>k&f=w1$h5a@({if<8c3eNu?~D|P$!HH>^#dqV%~1kx98%yua2xPZ1M zw|l@jp4V+xZ?!rde!g%TR#Lzc<#`>s@CsSG?GR{tL7 zGwN!EYqL@XuUtK$%NDE%gW$n};OMqYNTWy~Y? z(tc6>8ZE)4*LMz*)KW$J4;y7ipXI=F3c1-Q1m%AR-y3XXVBF4*@5@H-yODS=XYAH8= zFZ`O2T0thW5}=n@d>Sp^OQL-_!)jZn4I43MeHS2(KxcylJ09 zk757TZ)7bT@)y^n%Vv@?Pz+U^cDS)wsFr!kS?c& zw+18`o%c8y93>azgQrQa+}Vo)u9F|bw8I@A6-_`f1JtH9NogqVP#N&&1HF%OmrfTPoyd&C$2p%gf<=ZykGiMctRx-qC13AXsOfrM|YkR_AeZ?vq>g(Q0@{Cey*F%F1gb!nh4jjMSCBA^m7^4m*#Y45 zv#lpS7D>o1VXp4I-Bw|pKQ|OHE?@46UF%$hHQ?IM5IGs*Pv3M)@$Ep0i>O=mM%s0? zg9VxeStsme;A`oKR)NK!_RoNm2((Fznz!7d#xym~AL{)DdD}ZcPuQ?u_`c@XH55S7!e1ZNa+jiSMxFeo6!wO zpKQ0Ko=9mq`tTe0PO(%qQ?EC>R#RVII1c32DdrSMHn24uuE#R1{N<{E9`hR1Y~ExO zCBJ@~)B5RcW$?J>1$2+wui;!nhRcQ4jcMmf63 zU96-7Exp)(bObHDj+^^}nnDc1~?WMhwG-m|M)Y|MQ0a-UU3E-Xo)vM9whnt&vB2L#D= z1rU;2fcW}9BF9wz6l^M8z%;-D@Y(vkjj2bB?|g2lL#As9U$Wa*4_a|mjbXb86Lyvw zx~iIKm$!E>?yZDI2)gbtOjJAOr9J&aJhJuE?)}o`R)LgByG4S_lEyC&IgNA_v>fK&vgFhZf94+C2#*W=n!(5_2J^!fW5PW-=EWosDmq2^gOpvQA#Wfv=U?Yr$f`|T|o!krf z0F?C)ZhYF)r2jN#K!pdPO%nUYKMfi?fA~av3!l{x4gt;qG05x%rBhYiY0Y7irmVe& z)egxLS{Wc(N?rI@s_2$iySD`3v9teV%X4xioyy^U5{G<(Tf&w5v_99Sg8bjIL~$1= z@Bewb@a_zBVgJew2kdsY{^_Ws}M( zBiTu%LKG#w*Li=w-{0?#_dmTK=bZa~-M824x}Mi_WXY@}S60D2?tK|Z61?Ryu;RqN zqO5NM@)2bB=fiicMJkWpNql#;K`|~gNe|nbvbgvw7-`A=CF6@$uvW~(I;jTE>Mxiq zX3y^ZHw>XD47iEuus??gCkN{E#zVu*7_KrV!#V*Y&9ut*3_JnvP?apxqySsgPP{$= zsV^1lMLh24^z+k}^aq;m0-r7UO+SFrI0%ghJfKQQ+MC(?i%4*{K&WMRdVWQ%R4-(z z-GTR`+`+lNge2uu=KkPkk}>5_`dun-u={ic?4hdD#{c_;E5rZ&K$(uYa1;!X^9l?> zdV75b#`(h_d(A{1Qyp=yFXG)tZi7?o1V?wOh&*fthvPjgFM@5IMN29E3FqTi2 zp=#d7dnv5BK-J#KWk~|5hU&4uAlvyFjxsb09q;yw*QwU@xo=8~-f_I#`W)725-Fwp z?hBBUUxMh*N{Jd_GQD%(BMnN-Hy3ORm?I?3Gf%7zVdoKw6QfW3*PLeuXv137Ab^`sGRmx*vM~-z1emb%lQM9~_4HpdIw)8SFLNQP=WV^u5W%U=Jr*wDb((N5hZtH3g-AyWWy_yF zRpn4E17^>PwjJs^;1VgoDY`^`Z4`wfTB;IXZf}%eQ$^X%L9fY> zSzkkp@#6lYwy5Z2n#m&AsQady!>o>AhCkkOkm?n!ia3s%GH@NpQCzCsfQ2@P0j}LO z3TJT^{%4JGZzxZ}N8m@u7nC34jw&Lw?TE7+isfQKxTRd{H>(_^DoQK=Ilvc0mej2T zi(K0(PUvh9H7ENOEgc`p*_45B*2B9*s(+rJHLGClGAy+Ry3;r2zVR{H#r;i_X#@;2 zips4xip4lhf-Up=A7!LohD+BZiA|i_GSt!dg1mhRiAgY^5_YO-Jmwx-eQ2>Wg8$KN zcpDu0*rINp3N`x<+o{JkE-YBH1U?;VfFm~XzV?tk{veAgTkm%H0>7(o?IyX!yKZl^2gq&jSub00A9VYWyW$6J|}YG1q=Ao&!%9C+O2rh2%ct1d>iB&;HXR* zY5ctX1V)^wx@4P1!I(W;<;w%{Qsem#lilyB*Y+5V`W*I?S32Su0dpP|$02fv>L`vk zkSqv{_K?2^_mpMel0#Kh2Gz~VXXzoxHNk-U|67p8AFs5^Hu@6vuVSCT&gunvuQ=4P z2PYK`g>0jdx4Oo@{^MHlj8|t|<40`@IuUPoQn#9Q4*rHDKu0C3f5+r&g3GSA{ zaM|trbkoy~A2X+^e&7q$o4iJCf~e>}%^@*2bdO=t9CRT1RT8T}pw3;JN2%B@m+EQo|p@{ktM-pZafxLhB>BjdDF2>3G@l+DubBHy$IP#+jHeI(T$#Q(Y`EcW zghQdV*Ly{mBH5YTzx8EFVe6wV0bW%@-9;@RYA~hM2BQA_i;5m!O`#zz0}V=fPY%yC z2c#KU5!fOpKm3eFr|Ud}si^lUZ(vpZcvooRJ9p&X)?wMV+n7JVebABzBTifR&YOP6AqqxcVF?NG@QZWKv~Iv zk-MN3F3+G*aOe7-N$Ex^vSY}5&{>Q+ivN8Zs5~YY=}8y{ z|Ar7?!+wPOOMM>?j{AL}AC`sPGuyo@k-w)GzIkSf(H7*I*Qq7~aY*Oj-R7|0{jIy3 z@^(R@4p()T^#7nL5n$lFvZnM=>9qr=Fxr#@{<=G>9py8aM(9P~Hi>r1KR?S#=>7r3 z8hN>4SCd1BUaA;>7MOktKSlQ+`;Dy}*myN~eQl9fLYLEUiBpfE(zD~FnZE+>etz)M z-wuxXR6S%@p>G~n2pft$#`VKo*r&gs`sC9I^M}{4h=U6|`N%)tX;Fi=RMCcsoeqOn z5ql@`x|{8(!AOtyoAM+FvekY!Q3>V+5EQCCY})@9dSLz_)KH{Yk%s#roKJ%0C14_8 z-7nrfIjN6xgpN9{sjnbMXao+(MZMMqNiwZF zpX>%B=bNzFiV~+N8Uxa@;M+>RRr{O00Z5xoL9s0SV=+V7@o_QOBxGyFfn;8NBnwd@r zxAhJv5d{yIu5NyZT@WWCLFoLtAk_bvyES>7?FEBMs09PI_W`#3(xp*b6Mid9^gG(0 zY%EsyUC(O*YtoX|j$*hr-<86Ew&U3gz!p>Gv3|>S0{G!WgA$#%=Yb;PClo3TF5yrK ze`uVd$`pQMD41PM(1V&Iyx95QX)*&opmxZ1YVgkewEoZOD8!d6h{k$|d$Oh^8x3*C0kx zL4aU^^W4YGt?(vxC(;e-fmgTj0Xd(pGE6Eoo`y$0j-5r)Xqlct0i1kx`kXDn(*xCR zOpc6OV737ARSX+|sdZ@>^7b@k5e9-JC*WfO8=-022|l<0{r5P6{i_Bh*ZhnWVAgVQ*|}Mvbio}Eah_4pN#ne?H)S}Z__+9B`{&$qFY<2l7DrVW z;4bh!ZafQt5=!36e_S;z48z@T-Fd;X-uZm+3`JV^Xp_hS?>)2iJ=RfS8M--r{e-lX z3lIZE2x5d(vsda-RZhw8owa}PUpX2{!04jTW%@rY zMx}_FjE$Lqaa4$2|693;?>Nq$sY<&~Bf+K50Z!86nG#|G5eiJR64 z7mn5^qx0H&-eiD?(iHTVR;T0#T0Wb~kkB)T{VsMb&veT2Q5CGbY5XlTZ353DKk?oM z+RW(^w0g8YcZ-@yVLJr_cO+*~?O#bolFBeOb^tB13*%xri%P+1H=9Nzo9SG7)_i<9RcoV(^ z%Y^BHgLqj~Z@*%9Gs+pGu760Gv!DdqPU3~1L>>nvWBq8c1SYw!^yHL(iMw#hiK z{z}|D&Rm)`C>!e-BZBolh(wV*Ow#vWDOGE%B`2 zb}YZDs3%=&$TB}HT;&^>Z7n_24_$P8Esd9zxNjlftRgG(O6F0bDuw32uJO@# zSD8+)8P;c19|4=IEL44><_No&uj!Jn2}m3a4o3f;y<>fiY5$XxZ+6h_*|w-c)`P#S`dMtm5G8)Rj-GE5Q1J6#R{kY_ zYC75TVC9V%i;Ayd!MmwTzU8jss;=7qplP$j7m=jwOut@)oE!oMO(1Ql;zP+Vi&GpS zo@EVl*QeO!4lZyxu{!90mQKYO>EXGR{65oPc{UY{YtM_19QE@G43YyWfMl*j!-L{D zZW(i5AuohT&0F%7cI$vwUnwe*v)Hoe{u}6dk|KX3U<#Mj9jHDS@#(1cjlq80)y&fB zNK+dctkp~Dy9Ms;8?|bjyrvhrAe$?nWF>Y!@upN_ntnlB;AAKyPFwQ$Gi%Hz8$IWa zS_F~FFO^?*+GA@usbdZ+S&7GmxX!4oc2%5=(!D@$z8?^rWcZoT@E1Km-zb}rcJ&uXw#A{W2)=7-i zLfd5Jw0BV%$YIC!cm5_V0}!VwQ3qAC7JfR7rqRep7QJ~Mv>|_IJ8NR$@4G70gPv%ns4-8l2*Mc&zo>zx%u1l0*;= zs-RM|(NNbPjwmLmN5rn^x2^WPV2xE4KsxRTTX7%p!{7_wY^HSr2fQEhWt3D!KL3`j zX>wmTu8^WTFIt3(A(%L-oJd5%%X6 z5TGz#Gskc#Id^jwllem7_DBuuebN+cmx9^VZ|I;|%~8$JP8arV54DCrxY zl0S4^Z(-X%vHSxX;@k^_&Yy~@b2Ua!$`T2)67YIYk&eH2KtT{`Gv*%pFaHC)8|Mrc z-qKkobVFgOhHf9Tr<)!y#Y^!~Vr~SmOu1EAASmlYruO%x_-ORp6f3QHmQ+6h(NB{k z_cwuhvXK80kzVnsmn1P^GVz;<_K4%k%)t@C))*RUM1~UyJ#55&yDN$BCAhwUw!oQx zT`_G~dqe>LCn12dT(MwWQ4O}3^YBN~d(iXYN$QFMaOle^;x1nN;P^Pa3FtPnTCyG+ zQ^6o{c7fi>z=9YD{+D3T!-W-8x;}a$K28#gg{xxz#!P&_^;N%i@X%cH4m436+_{D$ zq)t9xgO##`NtshkSKpm5i$%}rzxq3bsMtVnavvYo#Mj9|h%;u=6Bnxf9K%PV-0ZMq z`~|g-zug);ZTNDQ^)Yrxj2;c%(>rK@^&SnTD>SF6;GN)3Eld9>=y=ya4+kciWou)G&7hF5*|HcV5n3jH$+r1(~0~J`*<2MCuP^m#<__Wd(eZ=yaLVV@dwW!dG0it!v1N!`cxnD2W8)QVvrU4H zKI7|v58Z0}5b>SZ`^)OBn~IkIUI@i~<{n8jSI4w9CUC^%^|dP&8icd#MB+gI_OQOt z#0a+W{by6$6F39}@B|iWi!50292 z+I*`e{WSIoY^o_gb;YC-5o{YA#{-t2EHfxoK_?sn`)`K>>Vk&6RW7S+V9ghA*{qoz zh}WO<9QLfJv3b({_D#S=Km}e>E#jC6$1J&xpl-80PRLUB0c#%R!-K1QRe-IskvDG? zV5FSt%ksL2nnrRz_d6{fBX5Q*nBUtZM%`?YF<>K zo)r07@66hU%Q?-KYl7*koAJ&CX*l1L*M&5c!sT=31%YvZRX8*jE2A-3ksr4m*LhRs zHNNQQ8x6UC;~Cd$L`=lBBTC{V#FingPEkC=o&@Wgv+tRWIO8PPW~8)Y@VTDb4i^|` zZz0I*+2t{ZOX2@Cm0tW9ix;`(V~R0){?K@FuiFmp>uEL1vGpRVkpz(h( z)Mt<7PrUFUZOs?o1T}hk-Cw`RnxB?2ClBY*KeM^RAo67_TlRQA1jS`fri5NTfx5IC z8|J>e6&DuXd{xWW<7ifHZ!IdDI2gE%IHg%;iC;`S{jB2$Q=5?S7?NQLrbh zh5S^eL66$hLVo3Aszpk&9)^yoAGllP!Uvvw0su+T^O?;AjTH%jpu25E6ld0Lp}|e@Mf!rMF-Szs#v6ba$c;0FArkb~tiMF5FRR|k3ctu-GcGnG-=~{h zAnQZ?ZwhJW$Sq{9kVdm*PWbfWnePCktB6&A2_aEKIC~0fL&(xHHaStulFc^ge!ke1 z3Z;3qA(6D74|5MazYGgBdpW#Ar{#Rh2Wonb=^zCwx(ETjmwwt7`?|ohm>Z4lXYf&c z3^)Ww_h~fO1cU_VobtdnxqLePgz+TxZoj^J4^|K7mI4#>Y#=~tD%4WyJz$p}j+cw; zX`LUrQ0+td;P@jzD$vP4DMt7AA#lmUfd^&+Q(@ZlyH_-|7jm=Cnc6_5_Teh2;=Mh5 z`s#n5E^tvuhc#)M3?5ET{mNPjukVn|(S>VLYCs86OsSAoMxRWccqc!#w6C z%w?Bt?hW}H!!Os3rSvlRXiTjGD#Fr512MlAX9U^Lp3~eTYS!*W9HicEz_S38AZJs= z2Fy`Df&-@YV~yt99XfCt1bA~|4n`%AnY`t8jBSPl-=UtaEh9F>;uRtv-#)pppY#G~doMnMjXCd^LD z$^!OTeaK!_-(vm-)f6Ipc8ldLU||VbB_RoXKT{X|7}C<8zK*?&05l9sBW;m5w^((FXsmIMl76e(Bs0 zA95kJCwKh{_odR@rHE?EL7?8s25Z`Wn9k>H3R8=E&jru|sW=nvl@9?pnUb5?I(F~4 z^?$HF_}4&I9#utiX7mrb^*L<4UVzyKeW|=FaQ6*DZ6?n_Or5&Z(;%uo(THjY2bf(L zsCEAxt#db`YJgOH2K5WW*UjvX<)4vvZtTSzp1cp~sg450Uc83{{gS~N|K!<5+A6arSR|oM1Ls(QKHhJI^|roD6|VePG74lWFZ4)Ql-tn4>SfJ$Bq|qTcIO!+dTx&bi<|7^55{eW){^#J)PvY@yP;j4bp*6JuTsh;pS&cbA^kCA4 z63+j$m$%&f zjVUm(VsTD|VNX9yq|-YELxU5J3x0%28gMTHEKrwz}Utp<>l)DwOlp8miHoqsb zw-t{kZt>g-Y-eIn;Js*h8(ajH%VK;CfFgCW{1(hYnIA3>BAjmTqBj(7s$)fc5Yu+1 z^ibfBSiN@;OcRUeH>2X&QS-?;qXG2pDc`@;ra%e$)8Ih1B&vU_trM& zPj2R}VQ0hIL@K~q#k=s{lO*U!1h>8rvz2`c>diK~7`o2x0w}(;@tUE_I6E^o}(HrYMfmF&}&oIZT&jo$QuZ%lWO4LDMRv8Q0t z*{!`Vq2k2TdO671#;^cR#M7uj+1yJLRM8knaGVQHlWsIYzy7JN({l=7b=z$qF%4)J z`zJk7>bbv{`WB7dZ}FfCW+nW}!b(BNqG_pBi5>_mtbNwu%O$B{m`xyQy%H}~{kKVY zrctv-?QROq47(U5hX1F1R|E>qpEgInsse+KkQ;$pD-$I!boM{;^BselTRW=sr07BI zhdsOhejxe1V!Sk}#mqc1o;s8f-AS~n{eVc=@9&2N@Tz)8EE`>FT@CO^ee|oWUgaGf zg-@$ts^=Ol3$`lzxLj6v?AQc90?*|Re84F?A0FAc2R-s}HgBno85i@97sQXpE`PFo zqj%&khOay8j7#(n4l?RhKO_jdsT@ic^;T>&sq2&ky`-t41K32WjVUttc;Q3`Zi5y% zXQmX}{-fvF^%i}E4DEz>udNb^vgZBW^+?C1c>O}0HcV|^U^6vt*i1MI54VVqEWmm^ zr0v1D>NY&0+CWPzw3vHSH(dHNCo6&&*naW}+yEd@^Ly;+h|O$`&mPxksQcceUy0BD z)lGeR%stR`#C_hELdA(cmLwg@fTU_cLZ>$p4l$YggQ!DEF8^+8Uas9@tb0e-SSet^ z-U|yYD}uPmeX19(A=T#OXEP)9-&QM+5nrhfVA%!?3# z5$7xIoYtZ!x9(BZ%U|qAu8XHlfrgg<74MHY0MrE9t6>)|sd!wLLL+dgg+7|LanWWn zuzVB{gRI#a5B>v3)U@9P#UE>^sp4HGskR zIrz0fuox9mAaIc%j>PQ{x0q@gOl`S{`-UMRhco zXo+~v)YX&AFH-DCAc-c+d&`wP$4#hP8v148i6@XGhqPU1x{$aEClFHP;>OeN1E4I0 z?cX53`;@EkN}#9sm2)unjR9(3$?)!!AKc~ViG!rwz*yDO|*uE8>O!w1lzl zKf4+MsJHalQFFVqIEowPXJgA(xTXbIwb|yl7j?oXIU?@N(Ngh?Ub<*ZsLd} ztU)6Bn=oXRhVZ6afRGANDi^YpOA~M0zjy=hr{&;&n7DYqIJGh67y1?N;u(nbG$(Vi z>ga0u*a5K7W6`Bc_pD{S=a5fu#;sc?9MfbKu z3qC2i$(g*r*Jh}8WNV@&99s{kz*&09*}^>m^KCAe%+J=)=XLX>_s-2hLZ$I?Z(UCf zbNC=l^iyit{wG8Dn!%I&!&ob2q9*1!|7gtW1B2yK&SEiRrn^qz{NqiP)t(3K7rS1J z#z@DdAjgcby(qe8w%&AJKMIQ%z8?6MdsQjk&=m9Z?R~$M+^Y|CMHOM?Gjb02pa&&p z{gQHHr6dOAa;!|hzS;Arvi%P=JD-)SKk@v`@>Xbk^Ly*=6%M9$Cj`di=k<=fx8{W7 z&y3FKEUhmF`_$bmif&)B-NE8nn7@=`29XpcJJYbALI+L<1P1@D%$dO(Yzc>E#|(T6 zX7&9GzbmBik|S0j&|)><#c`vD24>L}H#MRo&u3k4TYhhRDLg_;<&jn#A{upIi+*mb zVqPA$=Q|3*bPJNMrd(&jT`$J%4ZSzA~*;_oFDy5u^N^dvpLeNrJ#N5r& z{UNc6&74*}^^kanq7e&|?Pc?$2baE#Ui5fBlrqd_|8J!HdJWP|_)y4tK-1n-l8&h) zD=krv+EL6uDdHg{CQB)9vYBI>_D+3wcyaXcWJ<(K`=qCnhEkuNUn;#se{8R@a^dUk zI@7z7+=b;=gvBU0L7qJVpqX8Dh=DBWXbW%yj3QzNZ)~?uCoegam$#z%3pB%rAwLb|bx79<>CrE-%f_Gg zeaQ_gzaFqudu73FQKUoq8SH-ER(5N8@bu@CvHSK{R{eu%bPn;hr+9gen4oCBLSLOsoNNw#s8Qf-cHZfxMp6Ci`EmaP8|a@vm~1e^chDlERruWVdOMd|Iq_I!X|#WV zc1Zn%T&l*>e!HKsx4GlX#wGF(mocu>Gexr+B;riCb4fo9js^9rfuBduPT43;W-=io zE0vO{f5lX{&l;7n1zu&j_lI(BNY$F*?V0nBhSG0;dpyHhJSQn4(B+gcSZdGkRILq@ zl5#BjS_cxxCc&CLUzosL3{oH6^Xs~{Nvu}fW%1F~o(&S>bom?$!PI$m#sPD3iIU5| z--Y0iqbAX}fv#2*qtN3feOu9+JWg*+XDK$rl!sYC##!R^za;vZZPzLPz6}-|I(22? zk3fr%Nreu>#FQ8>bZA+h8DxTT2YsU2Yg%Ame?|3d`y?>EjS%ly_h zIZSjbe7GB;CQjVtPx1_Ff5FVz`HXnWNDnP=v46kf?eX`4p99SY`>hMqZNYfjZHl?K zj3w|Un}W6(!) zJIq@GF{fKV#mCjsW0VOIZMp=6?(W}-VHJXpJbKs-3HYOFq61l@d<&wBov{e^w`A2` zHY+wd&=fSMvc!RT$TQiZ{y!5M3fN$F(i-A_I`@w+XJq$m913` zit!mVU$6ZhZFNGUq;cwUSN10&+2(f8(MTFMk8<}Wqw8{+6I7sRz$J~%^0>N;3s26F zgxe#kzk!v=5W9itjYB78zzz2%ctonb6uZHWl{xvWaY&`Oj!3T(y5Y0%DK=BJjQ_Hd zMk($*lBUr88m^v)e>i10`|Q_z{8?n|q zY#@nIerI2UveNphs#|0rEy@{6Aa_T~ERU;IYF|IwFCTrDz1kQ|VcC+p`!reUhN$GC zdcVGF5t5DCTSCPl%o)qZ{AEMt%{7`Wm59eu*8x)gycRtZe)z4$oPJ7xczX3UY;EPK z=4YSTH`OmZ`gM<-hc<`|WL-d|>Ls4u_g7{hS0MmxI|#tvb5V*!`Y7tg!jtFLBkzHeW=Ni(!B0T!-X^ROUk2&Q6FhU z%;f)__|~Fj&a79S!Nh}&KCm#GXm>CBYuoq8kPwj}y9&+(nT}jXC`>Bc%?j1QBmQs7 z*2wKC#HWE+Zyn=LqP*KYH^#9sJXS+jBWTPUY_RIF08fp%3HT z1{aH%^3zaB8%tueh<#l=4gPn9M;`}?ceEDWLM%IlJDp)(i^ZL!m)0Fs>pi_dNyrEc zG)>FCEjgmo1T+@QXs2l3b_sjF3ScKI{tl6jk|d_#hT|7pxEx-LC1fp|$E~C)@OSoY zN3~)msyc9D;bMARo8t<_zT8f$#yl7IPcrmB1DT4%-~K%7+|M+eY^ziG z%o-?i)t-*;6dmr{cz$L*Buavq(_xC^F}AY#Wftj8X;Sl*XxIyxo$W1I2bg0bpff($ zU1CA7t&zyYN%YO;-VQ93Kp=#d_7i`jOBbsZz|B1(Wq_u)6GEei=h9)u8S zoDu!n)A`5y$2FS9e|>TW>xt35Qq}@oHRK-}zU)7@0_T+%ja0wrbK;4MW}>?=x{q&H z)SO6VWBdZRQ@*B)fb(rR-}uueTc6D&Z+S8!4AFNI_ppPOFLy;s6*gA?15MFEU%I^g z+$i~s65;&{bAsGF_`fQQ_Uve&sGc=GtrbY3Xruf*fj`K6iPH4JR-&;5+O;LaH4j~e z=RdOh{#Ho-0s{~M*3!m7PficX+aS3#Q+Zf@6`givA1C?I0j`GQ?SGDZBModJww5{l zEk{Bl!D!a&5}MA0T;X{{I36cqamm+HLy=0cC&tNG>-o zxOQG6p2~+wUC19zE(uG8Ff$ze|Kk!|OWsPU^kk3H$KrkC-L$;gjZdmKyBe|^`YY9R zXOxi_m#B_S$4?@IpCqVLUorh*3qQR6m0y7UzFUz7tDVNTanpo*gj;>f^`D$HRYyAGJv9k>(l-i^35- zPlz|N+t{<4L@Ki~qJx8aHY6#Kl;&hk60{m!kT|yh=jaZ5i(gjZO z**9)87q?g?*i^);dB~f5VKub@2Rd?w#I_W#4PAdYdsfcKO?dio2C@ zmX6hldem!3y?}O?uh0iXmLsQE;e_0d7)d{q0vT|a{D7B4X2m) z9Ip>B&)XA$W&`~|$L<*Ybn#_s{}_qF*K@83G(~3mJl`zPd)?0qqw{4x!z^qVnD2r} zF<4NSkL66?QiT$II8Gsm%_ivr;FfWyY-zjhn?J0r8UQ8E+qnwRx&EnQK$D&`WCkQ) z`o2R>4KdTqSzH5!^r}z^4(HhF7ias|WR9E@bNLH75C?p$@=Y0`ar<1vR~;7oZPJTf z5uEZes8h2s`8}v-eO1rhPELbw6U26njmq8Fv3&9W8DM6#n$=iR^g)|&$F|fs2!`7- z=EBhL^ct?xZ!Ci;;C@ch{0C~LP6hI5@~tNZ_g8hd{mCKqgDv7jsywN-?p#URVthfb zB1N?PK=uaKvB5iKdl@-Cc5k?K#PtEd(1VP2AqRICYLK@0K+VA zZ{fTpyZ`*>i@Wh8Q}M$ns$}NrO8v_+Kqo6d_B1VKELrL1_n-sKmSP7-1V4FhK@U1{Y37kQ0h0S;FLyPS5uA4Bb(t2C=C{uzC zz6t`jO6~7E+WI%EGTbCZZavcevy7Cget+k}iH{VO*d+ok{eapQFxxXwn_Gig`t=HM zBYnp`2SofTdud$r?rF6T?2H^jIN{*&n54ome0fq>t)^+Wvue-dv=kws93+Abtdg;>?n?F05_JYe7sn(KhP8;i32E(VI!Az?hNL^|I!PhBGh0xLkb4{(>+q;V2Bs z#i=^npDE{(F2JRianYl;zT>EK!z&NJXN~!YXkQ)l*|>mpdUmPO3_Wqjg3m57#&tir z7nz0cH3gW5jhFOl`_-pq80w_~ZGWOE-i~;n7k03>I~R|Jn~}jn`+PW=DuP{np7#hx z#O$jNCDd9Jtem>G?FGC`yLUfxlFt{as!uGw${$<%4L$MGH7wy?RiYMpR+juIs5cG& zU0dJf7;vIGFk4V#uraxRkU*~Ddx;N3cValbs#~G9@r0zjb!x-wMT1HUj(h=i8#QbKjcx zFBF_JF_Xin-mfJMuNladm64}`Q-e7G%UV7FL)iUp$ z>`fE=5;~U}GdnU0=!PBlbvh*L%^1>Ov|Hj%#_nI56yKq;b4B$H9bGJVlrn}s&=;)Nl%tZ2X_hkme#J*;V+OZSb zf97}#Q)8`=!d4IQ%bm_&l8>)ZTaSYA7YgZ?h1wH~I&-L`Z5@6$`X=~WT?C5kxT1MY&MXtKd-RIF>~`x%9&hWhFXXZU(K;uRY4D+e(Q7NVUqID-|P6$7wARbuq- zMTZPNcrwq7;19CBkywoxK1OBH{@pK7wGz#AzAciroQ=Zy_bm()tc=* zt+?Fxn`-aQfArzSPe(>{|BC;!98IN`ub4_EE{U9fH|)_q@A0Hu?$exjwFo)@EZa(N z;Z+1~B=yBG>4QDwesX-RWuxo{lUpG5?6gBdqugs1{3qQ!N)AfUZnoSPI0jB0nDN6& z+FY@ZCc>w<)z&UH%ov=@e-#eri8sEt(K8XPIJV8}sDF!h@}o=9p)3)KjUQ5Q^|;X2 zkjM5)2QJbq6e{@W4tJ%Y$Enp^8m?P{x&3d+tAyhRXj+|qNvjM2B2A(@8dbD8heUQ4 z3s!Ufz4>t|N<3y=RA>v@rb8>%YbW%_85Q58-(-JbouG>Uy^$Kh>UP>N%&^{&!WBl~ z!DH?d9FO+?%d8MdGmzz%7hA!ncL6h6Vl!b6g!?dTky)UVn2z@ zvmc6+UHe>xkRu_DpUX=R zeldEB7FXW9^)#*v_4dJGq~Pq~-wr_p;()bf-M|n`@dWB$_pzwF?_Ctu|>^vY-?@73%+g1Ggn7#0A@=UI)6gi_7SSC=`-V9cNK*K z8>+zP;;`q7vLAk8K0n&7|E3Y#IfSdPSgPK&xj&*AF`|1-pupLK@06-cIBpy>|FB0b zRh1HeP5B83i7(O*=33*$n{&YvvBSiIBChS!MP23g3ta$Rr8pem>>M{T!f9d{eDONtg zrW^#YFOqN3+%TpXy>fr0FikDXwwQ`l$xIEkif#-X!hYJn`NugR&xNAcPY!PVgVxwQ zD>lYnF1pULHlnE`9(*SB_(u}i@x=HlUbv#1NjZ*EJ6EcC=9JyDC76FHjTwNhVN(r} zG+sIcdJjfg7<|olGCYmksf#Q*8N1WjKV%}}U!t^jd6onO*AT-dT;k}tm?C}h`0`ao z-ebG1`cZV=7Ywy5nzc3`BJpfnbXx+IdW z+_Z`c3%T+3HmITU_uY!+r&XKQdxzW=y@3|@<#0F2_cQg$4>|LWO;tk`&+b^a$UNT{ zXK<}R>Lm!t{n%6ewh~l3aSIJszBwx&U&tNZ7VL}-kh-EXw;Gj-@w^ptT#1C{5*({D z@#0(3o)NfKTZzG2w&!fB*Ww180QZw@IoKjCOCfK+Zm?w)`(m=v@RV2i05W4-B6WUg z-%n9al2oRx$AqMT9JU^8=PxuUxVN5B^iJ=dilyIA-y=3lO375>%FR^E$J{;PS6QH- z@z6UOeRkAw>87a)o2S8<%r{wL1fox1g$MbWfC)*}dFkuKncM!oY^qn6Brq{!c zgcZz=j}G;^t{Xmg$KrRC9g$U>!Hrrtt$i1*m@LI919c<)|GTSj%$P{JE`lO zfu$D4OX{UAzMs$P-sv5caA>_2Q3@tcb!3e==Vs6}c6aW>x;L2Ue1M2wLv}~cgD~Fh z0DMzDwtlN5y{!P{MiD3akj4l4C>9%L1UEcc=z=M7_50IL1MNwbiJ#{67|$k{kliE5 zI7uJ+dM$!vsP2!*E4*B4>ABqfU0FTtsg;_~#X=qK$1%_Evz>GC#-Axp{qV#+!KUOF zoHSzWXY7*DYjOijb+O?ZX3AHRkBy=Z@{6H4QzjG!hzjh28s2kP+ou+2qBL$$4zde` zBa2vM{=LDL?pijjEW6g4rH7;B7W+_lkiPdp{gL)--p55z+ith?Uv~V79;S1TRpoCG zGzw5u{u#EUG_?M0eM=e*w@Zn41H<(4f#P4uqidl-=S6Yr}ZaF`Z=L~Rem6{AZSfFQfMwP`3mI`o+LLwsu2sl@m8eqSsM2=kDJbXS>o9@8TJ$m zf?{Ojx=3HmosY?JFG=QMKbB_QEoM&4&^E>71zYC3@h#D}xYqrYUiq=|`}a?A?69-P zue&Ml1R7FLJ`1kju6JtKu2+06y>(~pmaF-kSgdipomjp!du-0-z}H6iqRiqHJpXj= z6fKKRvNf9fSZyKe(M3Vs91P#s1P)Ect00(&_6Us5k<2aGqHm;IDSZc@WB!z- z`+UPKJEue}$blscvi4t3c*MSu97Y?gbL!l-;zmRU&<=}C-s1Sg3a zRKMu6(6&&vm4QCH8S>Zg{@YLAJU(^a8sF91Sv8!?`kJjzwkclVD=k59@z7GV$XuLc z`GiD5njqa4`-P%~q9y7_FNBh+{f+$9x7*zUk}?mgy7*PYWH?fTsVAgS>J&(ANJw{hE>1`db`^8pAdbTJbHfMqc0Rsf06|ROsXm-UXJje zBz{T=6;(@43`WmN#_&@r*h`++gRW>6LC*#lh3+eu^AKe(C1a1wZGG>OZNQ2P9Su3Y z!=BLA{bkNm$>`6l3xTZ6ufc^reawuVR>)oPRp(3dyb~;;*>-3Jgh74(0zKE};?*N= zRo_s8v?YnFjO~6e<9NOBwNdtReK$H1lpJ!e2G4Nf{d&}c>g(=_#nW`Ahf6wKXj=R} zd~b>vsbT57@7`3R%bTGqJhZK%`eg*h80cWTtj^B<-qre`M>td$>Lbl_H~ryQApizL zhs2@?jEUw!=rr4#$dnQpeQ%4NHsfx(Wm=PnEgzwUf^G;Zo_$F&)x!TG@7yDE(FRTF zM@yZ{F#qr{u%tM^i;p(rMbLPv718%`^~&$<8|WchVqo6|q7zGY0T#DVk-cYBx6VPg z_~*rG%A$|$8$miOLH3{^f%sj#Uez$}e&fy+lj|plNB**nBj1vyf9s(rMU9ER-h|d0 z?jlD}y=KPs_8A(_@GTNV&zjCP`&S-MIdm+a0<%eC;cj9p1~;O3M{<=f@s-$0&8cTI z`CzRh$w{>OOha*RDyb49i!oX^Mc?rplDK$q=nly|BN+l83ieCyBl6P*iB(>Wq48*! zF6>qKVp1uDT#r1q!B<@epwaAigIR7frwG&q0F;~SAYz% zhPh0PTvf&`bowWXE83hrZ9u`+c8s*oLi(P;$x`43<%b$A^0~b#T4Z~{3tg>px`qtM z{KX2gu12D4X^ww1MMJ&Hp%2;Ac~q;YiHQ^GJ_q_l;{&(g>E=!J_BU`?Fkv4YAJP07=CjdrIo#e#3~6H z_&w=(8e6{PW$j)Ga-x8b{Z+tsbNP)^)Cx*K0^?Ug1H^JkOj}Rt{1D3OsWd>a08TO& zpFakmDX*~7{&VwvvjePOKF%((B&1|?Uc4c!eYJLFy7|4j79uHAl~>^kF3WT#yCPOp z7T^F=5Re1Q9jg+bql>EJQ4o}Pd^Oh27F9r;ollbIE$Dj#&HLTF{5>W~K<2GC32`b)3SX{h@Ykw)tt8&eEu4IY z{8clfQIXexo{%3ti=1FS7CJT_tZt}(PH$<--h&Ax#U)x z-JNavzrvGi%lNjqe^e>`!zZ9^AEIxIRbvADu z6r{Nw#hIYz9@}ODz+?gQjbvVfbBVDY8-3AJ;5Njs;Hs~Fs(0=&;KB+;XI0{V%1rFy z4M?9VpTx8Q6AKVhneQs!7aUsuucrbT$6R8nEFL9Fr0MvaJGvugo0P%P1~?>@Do^Bm z@KPRW)wa7xy1k%8m*$)_mBD2WZ)X-dL{GGLDn+9O08fdN@rhyo4Io!8VCWtzNk1R^ zyWuRc%2;AmzHMoaOTf@z*`gOVz(OUDMvsfkfy&JBa)`B2^f#~Jk`@J;SVHT);qL|>$Sa@D2cXA zl5{ye3ToQ_Hb&;c4e|r-2;lSEGy(+^obd)?w9Nom3HjLOoAO4P2#0i*jZuiWeRqO2 zK}#;Da{V-)4*?~x$VZ5gll)T4e0>hg8iv9R+z!m{wT!|1AbC&l;bR1iw%Ha0pm}-# zm0?GW-kP{~Ts}av*qTj;PJQObhv#D>^sciBX+~5ptOMq+FnPEya%YD-2WuFY_N|3= zn57lb3>1O#p(%%c%T@P3;&l3sU6&T>zT5^Tu9j)ndlXd`S$~t0`Twx><>65M@83*Q zMz$Gigl4g~ShHoF8C#Z!vQ%VAgBDamax8-(%aF1}AxR}#sFY;OQud`qiX=;vEm_lZ zpYQkgyRPSYuIJBBpQbtI%=^6G_x-wG3mF@6P-DX}p1L8UBu|ZsK6C!tqbi89VQQ=4 zD!_3WKryzRZ2Bt}+J`$9#P6}G-hq>QzuI-@DIxu&gv~F4eyXkKyWh1l56Oi=$_4&F z1`BUKY-IgrF~cofr!#+n*}ORUeqX!pjRcdGTo+sc?xW)gf`k*-liJ`YUA}Qta9`SzgraGkTG7-rz03;)&A6J>)3JSYl>IY`=@=^_yd+Fj7JRv-pDEJx=r9im?vCYwpzbh z3|=wk&B9yKWWBH3^=5~jR9ZKSU|w|)J$mCFBn182v%_O$4;Y@@%wzQ3y;8O!xtHuk zvO1||F!i-QZuPmZ{_8)nd|TzT>wSKzxLw?K{rsl518>A_V|4BUiT!12lbwiQL+l%4 zD_LzEyN6pVArb)^J7{_dImxRJZs*HUhphWTafAxX|DRt~;enCAYHI60%>J*z!pc2Q z@gGTW(GiWLZGykSvzzgJ(|Kah%RWFW?AEfAq}@KF@hX$=m&a~Q>xxe35r5O0F=L?W zQ}qTl4|23~i4Y>Y^v||3i=|@Y4!#J+<1I&;SlA$E8 z>cbphShpJ*9ctCaFcz<0{Nw!XU;uEYkFPC16bOTW(_?_($_&0-a{d9Q>ctrUb>X?|&{7#&A?rq}S@-Xupz+Rg!22PW zht#z4Jm8z@8KaxMBKd#m(ZDZmefUSc&(20SjBL1*NX(|*ScJu(H>+O zZyOq1>QeEBod^CX*Lo$D5;$<|GXk#Bn(d(6nI?#1RmS#j;zaUQZhhLP5wVv!weMs>0?`<-`rV4U4#JTGc-HVD zn1MZY&PN=vVJr@v+a(@}229!VIko5Dt9u9A#>=?c4AgBnw@553ysu!OF=1-K8!#Du|XAb3_cnYP1*#TtP@<}Kvky4uki zjvEU*{{Er|xZ7;3_^&nz?2vHZFTk@p`#;YrSN!Ip62`!oqi0Lyy(MJgJvlKbAHDY- z2S;?HvB1PODK;%Fh-GIl{x6vTS9s~a4`HHR;-wp5h8yD*ei1d!c^>4R2A9{8I0$Ee zk2zlFR+P&(#jM3%Kehk)L{_fniiSzef&b*#?*DEG2WhE+{N*IG0QYu2w>MshQPh$J zA5FxhM)AK7EztK5V^2ba0G_zffVA*$ZOrg{n&qxp;-%B$Ov!u6JgG6M585*bI~(mzTomC5Ss2PR`5(kp31BK0hk>p%x$+c zYQD_MKmQ`~zc+LWX_Yx?Png*f3IF>rSnSYhQ)I>kU&rWt$vgt)OOO6@V4+9vZ}-0S zRpI~sN@2R<6^9axp5wsP&J3L6e0{AqI>YxgCBKK$D9O+kYy;82Jb^h|-$4;hH+1xy zQD2a|AKPsfF%r7OqrWs1-3@N1zqca4i(?do@?l21Rj{}8$R5->!HklZasXSG1XELx z#Z@0^Ab_Khav{hp=IR9uGnp5R(~AZ3L5}h+@iXMJ`{fKm{rv)VMYw0e6}RC7@VL7&sSG z*uxNxZMD-8^;!DJ^>UFS$%GpKW#aBA*FB2G7q=??OY-Kry1_Z)B2$ zGY&^jEPM6DaYGRk;t_1KCekEz-aJKGpWn|HJrP9e(PW9~E-LtiepnJQfB^9Qw{4^l zXK?*n)(T$>RykT1h)=7hs9J|nZmu^?OW1oyl+ z@RZb17dSVrXh){j#|dPht`TgarZ}u5ZmgVjwwJ~wnDnIe*z9R5;Y=UVIXli)O|i~Y zF^0fCMYLV8c!~^Dm29E{yee7*m$k>h#BkGfCuLY5$!GziT_D(bsg4MIIz;}W`p zL;W4)`G24G2>D-o^CV@kEI+bUk*RQpH{U|WgqkIBhh<)@phVTk8Y5Y!3trhwNWxiU z9~j+KK#es&CS5&w9+~c+4$Ap9^|C|yo&Vtb@4DyOLyP{+msG4zO7le`o|MiP=TAGs zv=%i+R<~Ww#YyP}+fwSC--Km-!SgGjy_;prH2QcfHo^^G3}uwT5~Nyw zjh9`{!XYO=JTSJvD{nFEi<<{2c(V+Q_?6&^A21}gi&JOlP%L;suKLQqoLW?$h)%&l zgx$=>rC#H;?@yDpECf^DZZL{m*h76Wa!i#x^8NGU%B>hxBKX0%EQp1ILs_3&&Cg*+ za>HAuSm(*7pNqV4LNuZsF7Ko9RwR*|x5<0$0;H}B&e7@#5|_o?|CpOfkXQok-G5gW z?D^yxHqU44Sjzj3mAKJr@a9`EsHLCn)6Gb}UdWuxiJaiGQ)cAfz>3(;U1xX`-kaHo zmK7DOhbc!C&C3}`l%Bup-||^g{^!D+jUuYZ&^Grf$ZB001g}*nS9=R13~fP_H^BR{ zt!)fI)v?20vxEG|+z`&24WEbiQ4>B)^~1h6{6 zZ?+JQ3p7&Zz_$x_ogAs>Hwum{usxNBPoL4mcGGHD>|7oiu?AP-^pN^DrdfUe%g}R< zL}M9*hpcxAIud0B2TZ)cW)4!i=75CNZ2m9*odu!nQNOg1rw8S zCQ)feJaJ1~IIVUw++msewPdN^-hOZ|{Sz2L9|Otg9u~Epw;VBlcCh(UKarXW zf@z7}`(Mck(Q0^bTL@}NY_aw`ZC!YC9451|*sx(A)yID4R~J&5Pc))n&B0AJF}`h+ zyPxk?(rFw$F@iv%Pzl>aUv%PUC>R+t%4>s#*a0FVX2z|q>%;bHV<;`3rxC+Z<0(Fs zeo5X)7D0vVMOPTE_Yjl7gq!5S$(y$4{3*xuFr)3gAib15?#dG0svla8`Y~F-s2CnZ z8R;m!nZ-ulx0kfN$Fufe=)Q#ggD^Vq0S42+YD!T(s$c>K3ndxk1nlb?)|bO~dOrZp zjUsn}(JgooCfG!rIALzMvO;GoCcrErObh&4?U8(km%SuoD9_TNC3Zl~>tw}G$uO-rVj>6#+-r-jpJp;?C=`p@G{SC$mqae_t@s+jQh5otx7sKGYH{Xw}Tyb%_S#8ZR-IZ-a_t6ucb z0n=F6t#8Vpezd;T>LA@^MYyR~nmraXWfmB}E!~a9#3CFY*|TC~k4ccP?OpnzPT7<7 zSO2Tf+B65?5(fo)A9|WC+){&&CPoaZRhqp(KWfriss$gdnfmy6V;g>*>Sb<|PTw0y ze!0tTzTxl(P$S=em+O0cj()#ug-;X{-ZCORSt?FQ5Yh2Fj>Fd^Da(#v2(u#fU= zSn*+6w$rEAx{C%ESDHc3ULaEpwo4C#Jb&_XI+BOJ!$&vvvTP3$%KyX~8R0*a`&?e( z0b|5767Qr1T9mR{d{@oiM<{o8-$E>}U`2MiXmoqSBOFo$b#sfpG{;s#0$0L2c*uCH zcYBT^1Vmep-? z?6_6z@^IeB2;%>>zwaCsX}VU`@WN2^377%O8edUD4g{K1re@YYi48D23hM_YwxHby zx=(<9Pkd3eq<)FWhK@*IXnGD zzxbH;6utlf;N2uNn?8VlrUWfo510=S0{lKcLut$Vc=~>KdxnK07 za5~Nb-P6ZAG)k)Yh<4yeGeypi-kf{k_+vHf;iMXHQR{OX2NFR#Jn{Xg=^|LPKAl+| zetqe<_F{0_mEW7f$kBlLV`}x6I_ z{RGOgFWVx~m)^X(>a$%1yFY>Bz}GRPJ$L((6=0!ucd}YFsOul>55^i5fZ%_8DU-j*Dl4$zFqtG9pBd);ZNKIS0w?xm=%*||tc{vr z?~Q`u4vlkM;hvmFd3qCCeutyHP^>ej$*%#nljOw4L|vASH-49*MMhyZ+keT zHsU!0O&jTrm+Dhno6QT3hn38>aM4f6j6jm8{q6TqCpuCrVcX;4ERZ3sF!opj(f=G~ zpEmLpOQEj!A3T&qV(Vd1?8NJkf&Wm%3Kt0=$oK!u_FG3Kn>5bw_}^sJr0&G$bOVN$^222&lkm!s*yT_6ns@Ea(U#{;;`>i<9SXD zN|Jh<$@7Oqu=j8EG-V1#mM-|l=^tfjCcPg8-B)3kF_`91t(($t5fH+3cIATB&2#LteNpo8lHLTsugsONF zTO4D`RHHS2LbS*uKmR`dxD``Mt=VZ{oE15ICB*v)|LTQ6yb3v8GRJ;*0wLdlbo!eF z#(-AiH&W*}zwj|&wl^>l7vlS(;CcxmznJuRQ)~o@Ey`Jzwz;hRlg-gUIH%GNS6$Z6 zCggijPJI){7$CHoNw2!e`NfX`f#2c7m4SzbH5Dn;faq>rHEdK|gqu0j?H!>?C^JW7 zD`78x`yGkbEZe*6rvZGNDU>0txuK^E!E3>lzAL88!xd5iHxdc?&uG3<5}0+fnzF*$ zvdOuB@m5otlW?-4gAR+Q=n8#%j(*#Uk*3v5d(}=)BJ&>t&b&UGgsb$}DyYd#p>jvR z)73<+(QVDCw(llh31w%Bh!ghmmY$l}ZBPCU>DAo-U>(tjA8^MPX*j8lW2%Xmwe4-2WS~ET}FD)vs^wX&r3f%t4v{0%dK?x42u=VA!{UwN# zDnfC;rw%{pSprU19JjLa^9dfR$Z31FA^`;sPz8D*I3g@>T{P{d))rPpxrXnb@|eUN%!J9&Tg$LJ^(yUCXDNzU$RmU?ngX|0c!WZ^zFl zVt}!I83v0M*Y!fwj<^@N{XunYT++ctU|YMVPcs9Ii+8stFaL#P>9kL$U+MRRn1&uH zk}?S~E?-&$M_M%y#~e9hidM^61{a@?blh-5ly%^3gU<6%W1=_(TDHUK>Ut}4puGCe z{`p$>u_>M3F2#wQAt;bLQXG z#mS5*==Y20jj1TCi@Jh7?yjwCn$S5e^S8_`7outstFG zK>cKeX%9{SLN2K3Uno_I2j5@rRF#!XL!`R;?2B`gMf7;TtZ#r--b2Q?_b-6UP&4%J zlnq?`4s9F#j;{knJ{_oid!Z^H0XDvv`L_2(eK<6JJgO)~JsWE4KCE$eZU~r38+X(| zO}a6#V+%v{*{(F5hEU>wIn#;f!sa5VHx3SbD)+hhVI8_NHSixh;HtO2^sVk zwnw|Hs5IjL-74Vfb!0uHC6y9~;t!$kKJ3xZL?MM+mKjRR*}CWM>Vf6a91M%bFPd-t zGX$O^S0R02LVIfWDy>0h_0ywcmij4db%XHn7hr!Jy3Y|H($Ur|p~)u=_m4EtS%gZ( zkYLPaEgqu>M2;tVw17`Slg(%|0xcer20kM8tBnJKHmu-$%@ZGNp;*4+e}5W)oqGbl z8d40sI_@qIRxCumwUnxa)Sq;t8I_9=0RB6_+P6>1;)0Yif)f&OS(6a=gn}wSb-R?G zdR>bxAhQQHjNpmoy0~ZRgPz<)5B-zy$`a+%RUe3o^l56*uIeR^*QE%oxaS7u99Y35 z{i5CGSVNS~*m6y)3^hDY5bKzL=4%;8ZkP^9rg<4Gj|lk;JbNfu3bwpTJ~k;h;8d|%;Ntg!i`L=F%hcr$NXkQE{lBL=hGDyM3 zQBusNEJS___0fmp>y6@d15F*~qxi|B@22Di@vj5^|4>L|@GaClm&IIzjsJ#rJvazX zI@4UN9iz_crn-`UnEIw$oBOpL84TMXBQNy$g$njEXbVi^d9a!1!@j?{a_%%qXTTF> z>4!(4)c!XD+Lxdddv8FhC_m-~`2P=Cxa^F9fF>zjE|!jr(tWw@@BX&&^VH$xx0Y<>5c6HZ#=bL8sb{_|9hnV`o{C+? z-IAs1)%#rXqBB1zk7Ac2i)U36wPlzFlkdyQl&zQ*BX6!)R`4=z2Zx*)?bJ4o>JcR2 z2B0%6JkDv|S2>1UzlYtPgUdfzld~6DyAN^|-#g7G_^ZMmlNomV6_Zo&*vn#CP9EN| zOLIbo((SlcapgwZUqUB$>O11LiLu`R9Hd|YXA5%RLW2MLv!@>%tr8Clec5zoV4(8M zM#CND=C~rAUzQqFhOyK?nt_vR*sMw4LF1s>i!(#Ddzpw-4EO3-2s!;t{ZY@Ym{_9| zxS6z=8RDH@TujGxF)aZ{=>|PUhu(ZEMS}`sj)P|eMxw+x`+34+h4Ra)SN3lE^0hrj zZ)7?9drY=@Je|UfeO;@6vy$n@blR@WXLSHVJ-X!B@c_)lxgNGLEXm5)JUR9{x`kJb zw#UkwA0Z51y4Y1<(j-I0>o!?M1`YMv@8bj8Bir9^gYmmuPchCx^ii>dN*wcO0cs1y z)aMp6$0}R>*$9D}>6N#}b|e+?JRXO6+8yQn=A|?yBTk&_C)YEoXhs@ESkN_e5bvKeFT1ohHI4pWpl<+6KV5rvl^H_bcOA=yP!FZHL}7DQ5xPR#T{3= z$Xt3f;vNeA@!KBqm*W^5r=ER{#S?}jllN{LscP&k zOu=VofD4g{n@gAvO=4!^>n*NWHq$tIlcKT5Up7Xv-Lb?eKbzbd&nQ+&>N2~cbijc} z2yB9{G2<^~kYwa@aI+f)u4k@{zdAe7?VC_9h82>r`N{5v*F$L{e~v@h(=|KOOjOym zq)?Q)!ROeoOrK1xBGs@jQ*||q#ExHgA`#p0q){%#yO0&* zD@o3x@qQ|?hJ8J!BJbh`b&Y!iW=CW52z9r|pkeI$XBJ(*o~L6n|K$9%>&s2|`B$4i z4z1T$jSg5cGPIFoQ=I+no^8yyS7(B><(DGdyBl~D;x+G23&@D_A!HZ(_5vTKhknw# zb|^GFpxn0e40HB)GJG#BW2^EO={z>kimaCy68UXk&7}-3d4V7+L%dG)t`K(*=`*F@ zz9uUZ1kN{aC<T?yqi9r@1FRa{Rx>Bzs?4@A^IS zi2iA$RmfU+Y|{x4f0Q)fkGo5jRcbzlLy{jJrZ$iE1H`l6`!hqZKAt@v$zk_B8YB2- z{V3VQe)HFWZYTeLyHEBzba3|5aLN}0Ub)L1+gHosrrtab#HIT#y1(}P*?bZoZpNmx z^I<2zx36b4^|7&Ad&tex27xmR10HuYJ z&I)n4F-xnl2C_9JN-pjKm)hoKqaFzxV3W_i)!*Rr`tZi(LOv{3Fg{-L75SIGMgm(H zC)z&7cG57(%#?ck1HkqCe))EdQO9O^2{~k~T&2xj_qB`}qP;RN#78c2hs`RwHE!I7 z-1sa*itpfB(Ds$9Ihx%}7{aJ1Tw zrm9%IxQLg(QwG%P>(7{JpAym}3u`GH`It%|Ii9*?{RZ#P1%1K4e-~9G2Lhz+cOyI$ z>K&?q&Nm6PxzbD^4LL)uBqpjlyhD0G+h%}eD_MKi-4U9rXNsD#w3?GR>=j<@xzDHe zAa|~(Knpl+PIn5sf1XyO1wD~4^hDJ<#oSITLOwR)N5L-Wtr+Sjlwu=35pbJz zaBp-!hkqGRGo(;YeT;8FTI*T19{v@se4K;iq4Q}&iwnztj>`GFL#K-?<$1129*MGk zptuF&N~thX zbc%#2VcuhOg^hWi*s&3V_!*_FnIBbugTe=@rQxav^Gn(~ShnwG9>0TCHRFb@GF7V5 zblbzY12DJkj|cl2n@yQ%k&lwxaab&88Jnl9Rh`(>xbRkkJhHO$O*b|PcZ}P>?*wiO z<|__Cz0TCY6#`D)eW)j1cb@Tv_nagDv68evi58%*F1>csy7>qo$${^~8!l*?GKZ6j z7XV7+jYK&!M5DEPE){nN&h}WN%mSZxC0UcrY+97uzUwFP)?cA^3rp&4r=QYpJh{tefG7V|&42;ngm%qA!n-%p;;I(DN zo68SGab1NLm$5qu%yH;cti+#aK3K&!g9#w$scj(JZMwSUW8x!b4LBPA-Y{+$C$P;R z=hpR-htRVwNk;-lI<~n3jJjzfx2Z9k#Y;c$^ioI*K_1A(;U6Bv5wZ(B?{_R-JH_LG zqE>QHil?L5EBIM)3g{7eR_!wtdU$E|%8yLBZ3IGI^Fd2wsCu5Yc^^$%GeUwiTW>LCYv2QUg} z9`(+B&IMEhbM7vnb}d@H@fH-q0OBTcT?im<!fIt}H1pojy_Ur}VVZq>0XXxTD^^q~idFrY1&eR0V^#14r zf7K-Rg~bkUZ(KuS4Olc%N5){3&g&Dt>&4Wg%+^}(0dU2^aKFPGqI@S@nH3rLHF z$#j4(5T0ehT=M%O^NsR*T~$ z2!Uf?K9=xC787c+gxWe_PU{669nxIAIcRWz?@q|7o^Ui&e?b{oI|)mhBRQ!xc9(n3l^4qO zPhNhUFm75KHsST)RDby$--JhL&(xlG{q%)*!yjNjuj93Ne^m@{DD2_wgPNN(XMbz2 zh**d2lRGARPr>}-iL=Zrk>n@*q<)w>HJ=^jin=v= zbn!+~@R>SiyjdJaz?q1Ip__~lEfJS)Aq_#{>P3jZ+MLzi?2@ERXiykGF4MdicVE96 zzBEDk`nzi+wj#O>;Zkp)rats=8=ddzR-ZOaVB*$5#C;Pr+V%5x>fV5L2Dxi~(PO|f zvu&@I39$IT!lo21mC=S0|+tL@m zboU7I;)&zcq30p6tUq7E=wAV@nqK0k9>#ux$$m zJ_uMcw0Qm+L=AZ%PVe5m#VwDKSpf7&0Gb(kT!(S@WdJZNU=X98gZeRjhnviR^e;;Q z6DTfY@I*Ggy6d^H)y^y^^)xKVk!$zMW42({=|o6o`&t+CgV(xYO9&IDATpkfiK(E7 z#T|20OM`u$n{ce@c_W{EEVXy?!-GTbm8Ws0HIk_EGS|8mcZ4ma%$Ow5Bgpy`9 z3G=-L=Ai@a9DthROXatlcZhc>ibTH?zTXCj8_BD)8WkMF#OI1{-`y7Y7q+8*wSc`6 zHLMFZX7!*}%Ybs(@wKB97ZjI8F$*FKaK@`(JTa+REYKm9LdFLwAG3=I z!w#i~b(R4Ry9L9Zz$Pi={P=D!-8c^89ca3^tRCcM*d}e}4q;(*`0kIb~1w>6w7yzDjJnV-MxA<+y! z`QEV`BIm;Q%KxgZjkaMXi0)K^qu;KL3qztljuhQE2Gi)V?O746M5q~3j;HV>UnHg%Dj!dktA}+bmFEwNg1H_b38oKR(PGN$o z?Sd9`R=-{@BCZ$5=lw@G-$n;PGV_W*Sk^^{ADDYYn(ly|PHg2-p-b>H-5X-Nm4&L+ ze4?NKgO|6v>>B`D7N1h-gr)X z@%QUQM)5=lem<(EBQj3;=RJoz!!MI8W)oq(sBj0A>Xa>w67hs~g)T4l0#tMpO`J^5 zpNb*(Itv3!N%CJ&U=P^~Mb#CYu{qHMuCVU{?@6Jt>yO_yad1miuER;ae=rXSz0D}@ zEpua4u)yw_zx!@`<8?qdP5MmTPu<+ty!o#*$Syf+GsBvhmd|{4sFSf1!_rgW(3_kx zkyruCvm<}ktaVh$LusHLNy14IBz-tK;v0n-!dr`IG;WYWHktF%S;|Ml=k`dqCwt0E zZ0#Mw-%jjZ{Vkwqtn!LaTFs#UlULk2Q$Aq5P94g&Eb$9@`2l=~#?qI5|2 zhn5l>Ss7;F;?YMC7TolZ?1&H9YXBfV8zhu~WzOZ{hZDDPjp~`bD?PFu9fjyYJ+=}R z>7PZ9gZ^rK=FvSqm=@}y1yEeZkz6Be0g3A1Z?=ct!0Q&lKs<;#4A*Y^X_|xWmxdyHE} zRdbghVXx$`-?>H#7yBv*B)5~dcQ)evrC>`x{8Y9!*H(j$OP>*``^`+j7hxoGNhaF% zMF*y72WLWRkPx9k3Trbxp;;V9SQpN0AgUGrwd?t2Z-it@bZ*w^Qb?34ZErGD*mqs; z$2R)b{+q^RE}qIG<6DnAtoV~JM7?<1RR$=*?@VVNC=*%e@=EnQ=7@rVo6%7*rt_pZ zjc5eVd~>Jwr~Q1K%D}*CzVyNycwtr15eR`aJ$0q67mt&H%k>xx+OG?a8wck7QW>cl zLiDpzmi~X_vAOI82OdHoYE88A9`NsYD%5lZ?27Qmi5y=a*ql2r&0^+%6Snrsus{n{ z;ZLsL49#?SFq;EMTkkB#;_T&t^tMNw+hQ|!)pIiFWOZtLPHiG;T_UZ?1!D z^lBn~$IY-2N+=J8?o>q!x9xyq7#_i%4TbTK5ji(C7cWM~@eDp~fcuVk?>RSctW(x0_j+njD0fS)qWd=YM4A&{e0SMWlbdp08MXI*By zy+7wS3*Wz`^+aKek;0u>7(4k|@TpnSq9on*=7Q`xlwXqXWsZ^C=J>PDu<+G3@Kwk8 z#Qjd<)(p{NLPka;5~|$TW`T20CFf|fX0Z9_!&kiy+NEOeURt2^f|7obglrRaK_6}4 zkx)90Pq1*)PeDw40Y)EUl~9Y=(YKp368HMjFMq!XeLIOvADlQAnZhUKcMP{CfZmUU zU^0hWa`I?gzbSj0Sm&r|Le&iF9TsH(U<2_wZ`{*4MGW}7H`Qs|u6Uihz z!5{9?e!Q;%->d|;_$VQ-VxL$fY(yk_xWb7ajBte!upg(xy2@vCt_)V#7`qoVbz<_R z>TbtQO&ra3&3}hhkdN=$w_JxHIclx8D`Iat3R<9EHO(bH<468i<^1;iwa>dU`~ZI| zk%e#XPW29H`qxaN!fls9=+=oLr|mQ%FM8*a!?7Geh}rxG0ube(K>nr~drnvn9&n{+ z$1KI-ze3 zkMHbhTI~?vMZUex5UQ(j_PWFcpkBU5i{b?-tFE;cyJ0-BcZi>p9DP5Ygx`n$oI=)< zZvnXOMqlf8dIJt0Gzq_iywvUEl6ls=k#wj}6zrN;o({rv{O%v$?m~+nGG7Wzc>X$8 z1qb{?cJ&_=RfmV!9ht0f8){q|g;}Gs8$wiZ0-qmx#_4X@|10va7Jc7Qc|$Nw`Ms$= z9zRBvj8c9+UXZEv+M4ebz-RbnW7%JfaHo4fVBv*JlHG9ZU$XJIA(Mq@JJMLJ>p=ZO z7kNBR`GW5x{)n;e3b5sTc1nj|RfOlSUM#qG^F-vDQ52EJCN~rEZ!wbu^&fh?-ntFQo<5f1C@)H1#TW;0452)V}>ijnUnkJ|%3 z-=Pe$XyI3t-K4wMY}K0^@aD4ckMEDKHf%yC$XA5j4ba&7QRApBz))_x!Sm#Rlu#rH zCp8ScOiYfv`HDV`ThJhI8_J;;F<@Ebd|JpmiQi@*Q5@wQ3VEofqMIv2U#gaC2B-n=FT@n&I+*UOaMpdx z;ml=W9HB;riA=5P62aYo647|i!>-G0ItN_B?2f{yG9B26cXe8M;;t5}w|c>h6v+U! zl$XS@M!se6b!y?$8psoOmC9ErpoKq+mul;Ph?()e)pw&msZgzIXQh?BPK8F&K|S4pMkNQ)6@dh-4q}|$3eV@$uwd{v|17;vA3@qmss&e zGVnuTdn)5`C6Rc$7i~X15WB9dY4$V=Z^AMA50rJsdr2Stq9|G-SC`)aPH^&h&uNG% z1ZuwZ-&`;r<3>l2)RDNmUHr@WNAux@!(oA_l4uWE8hr!8J6#+g?wtrbVtyJMBw&7Q zYI}~(mGOCMt$dP4p730QfG4yWY9P1hQ?sj!^goVhP}gM6ZTKtLXOX*ILpN-Mi1HX= zbx$BDortn~S^EQU5f9ppIY(UG+~xzC3TD9#=zY7#HY`f`ef7Ih+>VMs2>#AD45&vz zdP1TyW4i+$>;kQr-$5U{uC9|YWi0$gj^+Mu?mv$4p_X#8Y$@qKkUM1HVTObR-&`52 zJaao-WWF0GaQ-RXz3Vea(76-1LNn%<@YR!$QgmqsKRPK+2IABXSt>r6XV){M7X1Sq z%TAF~C|29Tqb!t`nl>2oTV!d@IGafAeGt7PNovnQU}Key?zH+cuq|^K$fLIxv36`m z-1vr{grCiPu|BPLj`E8mXuy^)QzeVm5PV8f+uvv`PO}2s+a5-G+{eUmU^eBvbT^9@dJ#IygcaK4#=4t|d|TUP*b=dh86o0~i!L zz&PznW&Chl?81m9R&pDu)e|?WV!jN0-R*dD(jGRyIsY62v=TF3 z0F$SmoOTw-P7ZC1%t~_)E=AJa9uhS(cKI~OKP1|<7PZ$6GCwcvaUtg1gw9q~kB?Au-_j)fQZ%-^X656jA$&zK;bCM-GubKqgRj=R*2$vF)H{DMx zThJp!VMP@8(_b0_uGXlJT4J!+k5|z z3@2zhTj!vQ~1ZLL?`1#`CI?8krhqeDfllKv#-NhA7eW&@kH> zyFLJ+ylRenVtF~sSKx%4+Eb*i@wXY=5j9>TJd51ho(s>ln@8bAa;Lt1btW?hIa~xK zHKNJIYs)U?lSWeM3!ikMhpNHP=we`G!JpOMnMO@ene-?!c@du?W#B)dbC`>yq${#I zX+dsqC-z=d?jYWIxSaM35a+^}O@RN_xf^7+p}f{uY1OI@et1ccONSO~(f4R{n( ze$A%Ln3a&sU%PbVrw*Cvf*-T!jdSHsO*zNIeZOg~CW&@R1Wrt-b9gzY$wp^oQWHj= z24W4hteV*}GB~@gI|IfYgnX#*@3}>aU6yV1yBWaSltCVd)Ns8BOzwzJ_y<4cPkka> z+gF7L&T_2x?Z#I-@8i9Yh|wE09PoSXyJ4X3%5LmUxy{16&H;5yw0oNC2#TWR2m5MN zv_vIm-5Z1pJeM5_LI-{DHntklPxoGC>M%U)5KV;N5Q#s|RMu ze^9gJaxveyW8pkrKQ~tk`sbK#Pj9}v;C$^?g(mhf4!wXua zKhH}bmtWDPohl{Ys5-g&FSXbu<)Y3NE8UNNPiBFWOUNJk8Pe%^!mg`DpYuAAS|~6L zVeE32>NQ6CQlU`77s0!+o^jyl{R2^DCsWSb-~~Ex^c^#Qt{L(nI1tu zi^$x)Ssn>$5;G{!mIEA5T2GLU!sCoj2+}7MWbf)Hs>xp~OffyDQ-T0dGkl^SqhX-YtQaIDJsV~IsE>I zw+M15zZZ|+9ozh%^4#RX7k+ApaYU!({--z2y>pJeLK@nRUWMy33q7tv*^C8KHT97!y!#v1C7vqi%7H z9?Kzaj>Zk&GZqy;9CXDDO7oG_q(?rD%m@>cvckP2OUAFz|!w1huddf_DA~MV;|@N{`IiCOo#;p=8OvEelbX zpEC`*MH&i(JFg6jJ`t))fjiHlWh53e-V5fVB-)#==O8OjXMa!(c?N1RIfFnA{Vo271xqnnw$NW-BV_ioUVS{7_s*5N)9FA)Gfyn$UNVy`>21AH(H~?!d;quz1 z`tD`$N^09e#c%Kuor~`PWIFBF=NFcPz`xyi{~@gZ1L%FN1p|mavtnrQ zyKXKFisDH)V*rvpeo^l6W&D@Qiw`uRD{%=(r-KN|EOgoKz1_`?+w$RQFD=$4VeC9s~MhXd8?PivH~zIRtObF~B~_ zgX}_ND5&s8;PfK+-rWIb`YQRf;C%c6?H#vsgR-XvD%IcZD#<0W1F=gHL)9NZXUNzE zWbvE<~mxmxpQvp@$ z31$?ST=ES`0FE+ZiJCtDm0I5mOQ}6R0%% zJNspSK8C@F#PB*8UEsdV>@!#{L^aqJy{L!Asv?1)u{Z4G%=Z%>xL^@ZoW65+{TYvd z(iY9r{lv0gciXn2Kk}b5>|)qe1oMNn&8P^IxD%KPdobt9jo5tUy6o%wZ|z0f03xtN z9UoE6DgDB?rIv$HAs$fOFQJtOam|0`u;q6}ic}quqUlvNk29%6k6c7|a-@bI-B>bVs ztV?Oaz!^EHzJepkfh$%!meub4}on=Sn$EG?O~WAiU& z{xAwvS|A`~s;K7h!Pgp8XOqtU7aJq}@3VcP2Oe$LOerD5_VAFB`QO{7ui_p;Uv|Q_ z=itwNq@s@?RJ06g0Sj2J4wjb>5>@CCFChtX1#+i5mA+asX@B5YU04LU`c*L0P@Le_ zO3EkHH8uOBm;zq&C%&45=1C^}Wv)HFwTwF^PMxeV!Tl!|s*Ewu7uePK!NJ3n*k8<8 zvn+f5L&;htajWUGA&w{ z0@Zt2@Y=MY35+Z8k$eySmrTHM#J_gq+)%W@o1ISw3f6H;f?qr4K~FGo4qS=vus=+| zwC0^3Y}0rC?JF0J!wG!?;&M99-IRjO)YL|3k3JygVayqxx{wvvXs<#m*pP&C?sanL z*zn@Rcbw7GEYFba(Q4yegFCLd(sA_F@Mv5G3>yd4!x(#_4w(Wk;ubI-2|{RW>zz+# z2U)hJU7gNJ!O7Sv`pdz?7R-WUtrMJ?cG9Hg4sa{JSIP80JZhU4Pcq|n$pVPL8EN5- znAa+Bz}1_vlqj#b1&+@d4gHRNBR#AE`JD?|QojbjMpxp9l)$$^`)7(ts;r5rY zqPxN3NWv8X4+USQ%%apbL<}0rQd4(07fzWHT`qCaahEm{+Me0s0}{_pzO$YdUvrcK zD)01(nEX zd+t36Tj|lT1A->pAv%*Kk5K`@`#ANH*f>>zQ-Qeety%WleuP;WU7z__f7TiaW6ao& znbcT%0NMKy_^?KMZURwp0 zH|9myjH>;8m))`!@I^fr)NTefWxEw#xU8_v$x)Cre>df~6M9=!KRj=wR`4oeGOy0w zy9R_>P@ICQhzY$Y%{v$e&dP`HMHK@Bttg%>DqZ>FQXR3gb_2WX*#X2+i zDKx0yI+BV8h|GPtFg-Cn8@JOoFT!-s{KKDxF<)J}J7&)BQ232x+3nfiee{dv>F};8 zv+^aA?x)-1+25U6UX$Ig2Uf3SSpe+lAA8V?z6 zQgzXdBClSYMqd3rXkW<`$_Iypdt14FN`9qmxWBy+DCwY9+1KWQYuJ7>2!N0_e^@xQ zJPqpA5cO`)fZylh-&BdOCYBtt#nz}ng3K$gN#>~DCgkgY*Z>uCW^W-f z&>oh+dToa5*+L%&Tj2xt%EvQ%w>vyM&qDC@4eFv}y7!G3M2pNG$-3wwQEK!@-fbWK z$;_)bp)KzVulVd-Svv0_I*+-(5zaKvoH8$oz zw(V_#v%vIH0g&YHm%8cxxFD$&P}_zC2> ztjCF_R|W7<0siT7BL@0pY`pPy<}^WPO6AZV1M1S~>;)@-MyjpN5Hm?mNlzjaPI5Cm z$skJ2_k78+Ny3G^f<}(lcjrw*HP+7`A>W%fHQee)z+(N&rvQ-CJsbr2nrAG%ztG$A zS_%e|0XJe`3z8Co!Vu#@m(jzlnCj`CL?Uzqrt7y+9T5 zIM==xM~2s4fGn|HyN1)XXHtU3+Zdtvh8vii9ca75yl7ZIJ`G@ z3(|5kQ^e5g_bfcn!O$fssg;h`DUm%1e3TR!i2Mv`+W!0G$9qmz3{h}hu=qIRlE=J-HI8;FfTnk>P_@iu1X5JC%Mkx5h(rt+;k5{Xy!A$gM z#lJcWM6iujWvsBJte0XlU_|0|p?Ib2!MI`)V!v|`ndNuQr?~nX(G%*ty*~ zcJcb!NP|QJJ=q0P(ZlGi7hwT3D3sqju=;X9{TQ&AO58FlA%t^siGbXUZ_4Q;y$&72 z*Eu2hq(m^$@q5UvlSFIS-*V`UHb7{=dAp-3IKdHWJofj{@|nx{=SWc&%?WU6=g2Z zh-6anp(juaoB$^a@s?;7WKPV<`-K`)3EFKVbdw&bq!*eNC+y7E3)ZkX|OKy#v&xNB|SMtSA+p?yM z02aws^(;b@=&z>xZ;u@I?{t7+$fv#c_j?8Unj($` z8gZ;@e^EFJhUhaY_q6OU#r_%nBcicuc#+N^>k9iV7CXagZ>(!14(IoiJQ+1~lFm`a zV#vQiQF7$&1zz@yCR=2EHr4NthL7pwMupoN+VMtCh2Q0Au;p3u3{t63W z`c8fQxNY{+slUI{svL|@iF-vV=|(Ab}m+s~SH=x`M|ZM+jqa)FZYCA~sr#3xn% zDAHy0m(!cxnrPH+V4Kx44eM=s`2vhuAP?dtv12mJiZ&?bvHk zwmBZSB9ZlwKqn)YZckH5)9p{!Z-nPbl>P0BNQbWT?Pn{H3g$S*ITbHXKFb8pzT0EA z0JdBuH&Mu#5`4Q|2Df`YI$uamVuOPs{|)7xh7c~Gj2D(%h$ELLM%In=EmG#Q`-;@y zP(MF`?wpj>aj$un?b6J+S{esDy`nGXiwqaQGR)d4bZR0W7TV`LSb?-K6X;H+ribY6 zA9`{R!$?sCY{wjW?z5w<_DH~u_(U#BCLT!dhcxnaw$(@Pm`As?k6r_Es&z?rlS>4~ zz9rV-oPm8x`qD$i0wtskK$m9624GNc(9R&Ab;#QWt@2VvRp?$barQg(k^A-n+-G~6_?VR5Uok|A*d-%4RThc#kCpkX=4 zZCPr<*HdE&(@nGGi)l|Zuuorot5j}y*L-iM!(C6Un+NDJmBA|%9v!{4!_kv^{?gbh z(^qoIlJt=yTl{W)j_aXl;mq|o7|uPfx-u*(RfcBjzr2ZOa$*z}@!U0N5usYwDH*aW6z0gCe8=?V#2g! z>5PyhglgOaM$aA-Q;WS2vU#Ewu#0~{#H4g8qPrK^OJ)XVi#ou9Uriz?9w*c<`F{{t zf9^8e+}rt^1c+V*op-qVU%)g#agE^i60S}IRV2dQu)7#$q`@79=zo8SEMo^_&E_y>#M9g_Z zN`EAeI-HYLTJwa=SEn+~Q4a_3dBJ^Brz*AH;;^}B3Ecaa;% z7rI#|A=*yDuK6}%U-EOs^(*+9!v)ww{_g^;PFJiyCJh-xt1Y;FSTeo`$E{Ozd*_D> zJwF%LX!mSqFOv-1+xKmtP|<}btvm~Y^qg&XvB{?6mF9s ze&JY7&LeL616z4I*V=Y(=_HpA`~iaR%nh23)MpV(_@S1?#+^c>`w+pKM%S(f|n z^1RhdSDtZ!%QIC>R1n%cE5Y5@jJE@yzm<1X~?DOlOaN!%^d*74WOt3R3jOW` zYHzeo@4(FBd$%V~aO>)IkdGV87F{5|6f22gi#-I)r4d2oMkB6W7R<(-9@QrERfKtb zm~=8k=Q%rog1#I{+$KkpP1b^*i`;jI9{3dhuCM=$;_&JBG1S}2jA<1^YchoRn(rGLSqQ8dRy!NMu-@%ojnr#~Jxl!+~6@o!`Oo zHH$CceD~IqJ!Yr6kKueKgsvH_y=vuvCc7QTXO(k>SSZ!@NH?9ZikNtXyl$uPzAPc# z(d}^0OTc1+eQn>cQ+!>=bnVG!mumt0xdPNs0KJQJWQv8Xf0SZa9fm(Q)vFVUgK$L%x#?aGw|OU-1yyoDc{S`81|NK6WwMQ5Lo0BVQvqvF$YL;<)e9bxW&( zt!Dxwsb)xtla}9jj-T0zPEt4?9J{0TApCJxXjrEtd8DiR-9og0m-xbDwb}Z9Cn&^> z&%$VN_qV@r4}c#imc;iR%?0?*y^i zp~`MhJ?PT$(wq8hvYHn*<|w+RG{Y3qfJhG7Bp3RsBt0%5oU~`q_Cmh8Z|M@T2ulQO zo|_^^-|0sw-2=I`@i#*_LvZ9?2u|gPDs$kK715#GuCoCm&MV$iiGgrgK|Qgo`pwxE zCMoCvXG*vy#moO zyr!5;3ybad0bjvV4lFc01k~i>@!6;6CMcL!(L>0Uu4?O{UOIQ)f+o%7^4E_&l7mOR z<2gWhyiaS%;(>~0BH{0|dFa2M7cr@Lq)5B05vhDkmox|Comh>MfkN`wet1Y}LDqh7 z_+GnL*RYMbj|9Rq{(AX48J!2k@_kZPNigmX()}02Ui&pH(W9vMF#jb*`@t=Tj}mQl zcOHf4k&qj0PlIPoX^`!DAcUm-|3Xrb`i;hnDFVrN92z(;%N~<}f22CEo=~W|55oOx z&$*!{1)TY%|IYv1;rfSB3_K&ctszyf!aO;t%z=d%?DN*I_^g8fXZ95@dh9@)-fI z3FF)pAKZ5kb3PFKG5cCf))W4P8=e{pi!R9kLM#3#@Z|>Ter;@qac#A6?TcwCQ8p?FSX+Z+T&b`i?|GJv} z+TyKKZFle8=$$1Ods(D*m~Z`S3^dcLKvVk) zZeaft!`V;kpo*#mDWY^@DwGo@)webxbmPs_L-OUI1RN~QUs%b}7au2_)NBL#Wdz~j zI+pbeC>+DeXNrFMdV<3NG6Ud#&#Q}+$ zha7WOjognMCm>K3Zob0RQs#Ly7l=7&K$v|{S2NBTGDX;?=#unpZp3C8R(NJk@!uUg zWx|RoT{Hy4pobqsD}Zcg^=!8CnVfs}2{kn!LHGECt$g5>u)Lo3)Cn3>UhpK`bvUHV zs!Ni`Wnf^fSc&MZ0C1n}*?UU^4F1xE>quhbmG{}{X z{$mLx{$JXfW~x|nUuU+4~yHs<_Ngo^Xa=Yh;XKBCu9qj^aK z_V5C+GwyA2{IU5%^4}~LRF!TJHF=Ele?(q#GeCaZ5dPL>@!>A%PlBtNII;0WdVbUgrXfGfF(h zJ3M#x17-6~Fcs`zCqReC-%Pc*W;B7$Oo1C|wnK2T|Hfhw)##w|hV8Ei40dK=o~uE; zRxf#X+es~Nu>{(U(v^}#Re)xHsPEr*Fm+3x4J3{))eR9}3$d{QZ*^>(X zF!5d;EJGy_;Mp~{vZiAEzfuK->CE9`uL**3ov4k#8sGgogu-JZGo)`hNGz( zxAz+;2u<|Ge{c(?$7QkK<^%qfdSX>)>6!mTM;=nR4)2~>nAPu79mlaqC7_!?$ts`1 zV#@@Ij=?dtCNBCF!4%{@kx^`|nVbaQc4?5=ww9kllNpNkH3^d{LZmV9&so9B+Yi1z zu7OAx3!kL~zs`Ig!Ey!Wkp4}V?PJF-`5pm+tnP>Sja|94-zD%yy6$5`UlGZd+(}d} zsa>6^={s~NbSJFD=r|E%;YR`v4rmm1g>zGof&xh#(N6T*l~-+Re_|UmESN#owuk#F zjcTvhtQ(uSycviS4>UxIVIE`rWaF4qR9M5y!^U08uL{=wNjPB{&Y`PNDHr~|0%;K7 z|2qiA>);4CXY#)u`3tJ*gkE;+9t6*fSS`!kV}KHjq>_kPaC9{7M!3-qg;!shuKwA! zjcEK^u*7NoL?OvhsUaH)G5E9te2rs|mpXk>E`uwujoFAE+&%3?H4vwpq%#$@i;Fm> zAkXpDpiSoLET0q(h~z!rf&VlN(h%1JCjTx)$SVRBdmnb^62AlLYcY27TtFiB{GTbc zRw%o??Dvrm(dk58p}z2V{PFmIH-Ah7CoXQ%ZjY<{33D^0U-?BtqH{=}a`A`gRfXcl zA>eQ7CcK0?qkp@=xvCRNrqctj#^9Qa3E>Q_z9N|~w$Op;u;WcSU$>2uLOldrdyA3C~m{$()#0qzjlWve zD{?N#hA_M;z8gStfLa!UU;CVi7>?gv{~7_aEUN8B+P)%reLzclxt(Bxcb?g=!*+gp z@RlM1Y$K>ppLG}=yr-tzLWW1%kh4RftE&oZBi`fpIcx8?f&>T0L9~&9cdgbt$pU94 z&10+M^q@c|%;z%zZl1u|B#D8Gb5LC)K9Y{3>#fpxx-t9PDBtc%RTDFZYMD@;a804Iu@FH@SkPn{uwF4-H6*X z&R2Bjs_YN?Ije%UG)=&h^YRXin`|#_Nf|7IEFoi%(V*eNqkwxC#bjjXJ;5m4(E`Or zP7TsiShngaK4t(*V*(033+@SF<+xFf3b9u7h*xXOygx^5WY_7y+H2fLTgVqNNdHQp zeg*Z(miR-Gz`#yCaPul3c&mdqU4hQ$%sc$eDX{ROvUmPMG}l+?xVX@Ha|!@DXb0u? z^nTgXmPR_zH!^o<)JX|p(sM#hJlG+Ui{O6NZwSDZzN#%={?+7dF#>!zsw+prn~Rl% zwE=>#{u@q01t7lFhmo;8C#nLLtDGTm z)=_75nUvJ6YK(9(qeN@U1iS#5a9Jeen%*a9yy%WxSn6UK>V!LRT$iaeAC|>Zqc>mu zq<+Vjps2b0i&&^vE{IimqHaS@L9eGr!Wk#<710wR{h5-h+p0}v!dQw1Q4?Omy1s0c zq&DQ}=dma&dP$kprAs8V8MY#zsc)G?6~bI(1bA?rW=p0}_sNFx_r5p^$`CS^59GWj zkh4_y-6tt8&y!JA^H#UyF-a<4Q_Cg9o>`!6eWPMvJcX3gRMNzCu&ap+@~^kJ7-h6jg33Afj>Myfn!(hkw5WOMTU>fst5C9Gq4u8jU;V* z=RwpI$1mAk10NWeHlAF~qMHwimI!#6!z?Rb+pU9`ofrb?hT7)ja{#O>7mb=3vWZ$) z2%+wIG1PHO45S@)VeKEcd%(fV`itq+*Sbii5*N@#obspmvyKXf?|QMUNzGWpa6OLk zMeK&p7`UEIz0lUNDb{-MS}eIY!DZEbT2%8?CYc^xy^07o_8EledU@Xk2azN=Rrj(H zL&fD(J`!S_BJhRMI2M(O7VFladyz4YcA+oS_@9CbioHZYa~W1CbgVe;R`Z5_O*H91 zwyG5Jb^1s41))q8X(X>)zy=3C8sm`A{~QwnWWN-Sn&;*!L0;UIV;z6Oh*kqbT0wX=Vd#KizPQK&cY z2R=2+vCx{ArzH<;=w`4> z@+AB5SgJBP4vCqr1%wA4-_$qkAmpPcU2@SOk>mruqXR`@1-A4${P)ePoo}K7pw>7Q zOY@HAd(0g#`tE6+b{L3*3rVw$l}fVsa2~SV^MsxF9C3U*v_MK5-ZGj&Oo^$SsxeaB zn6%OEbAs}Q9-iF}^_E#CBs)WWutT!`?H!;Shl3$Z290@Y$WC~E5j@Lc@X=%qcJdY) zybS61Le7rEtd;BO8#_YXQ*^@xzJACGT^JNHCY(9!PmiwYxA{p))D-%q`IpOEd>@7J=(+UPf^QO}&rhSCytswwcI6!?J zLJgNy`?9Hhy}auNoM&5jO<@?~TNCFe~!&MY9hVdxYQ$hF;zAJ~=fA zAOOpqyMherHJAKi9&bRpLj>`re2e~f%`TLi|(M%V#e+WW9TuiYuUoGX5lvvjwCOD0Jo zYqr-~hsF?i+Y)$Dgr<5~H@4S$yv%g_$H-PruFtABQVn@P1oZ=!eVp&i+aZLL+v`5N zeBxMasMPb_zGGN;X?Gu9r(KH2@>VaJ^ZPCD|c|$lzy?j!!IdHhy5`fj&8b zpKM5Q77Fn4P1fLgnpK9#mr5+-M>IiRB%(h~kIvNoV+?I&^VF@OVJiGEz@KLOBM-H4>owH2|ff@MtL7FoO^Y{fj7 z=lBwwDL0Hb;yG~yugx;!PoGa$?${$OP~WFHe&fD?Tzug@A+2@8askBQrA=?)n zT9D^&>@1RxU&KzIhZLR=j4w>@FnWz5FGq+IBpl+|F0YTkk0r@KHuu>9@ account.keystore +``` + +**NOTE**: + +- Replace `[your private key]` with your Ethereum L1 account private key +- Replace `[password to encrypt file]` with a password used for file encryption. This password must be passed to the Node later on via env variable (`ZKEVM_NODE_ETHERMAN_PRIVATEKEYPASSWORD`) diff --git a/docs/components/aggregator.md b/docs/components/aggregator.md new file mode 100644 index 0000000000..a1c314a22e --- /dev/null +++ b/docs/components/aggregator.md @@ -0,0 +1,47 @@ +# Component: Aggregator + +## ZKEVM Aggregator: + +The ZKEVM Aggregator is an optional module responsible for receiving connections from Prover(s) in order to generate the proofs for the batches not proven yet. + +## Hard dependencies: + +- [Synchronizer](./synchronizer.md) +- [StateDB Database](./databases.md) +- [Prover, Merkle Tree and Executor](./prover.md) + +## Running: + +The preferred way to run the ZKEVM Aggregator component is via Docker and Docker Compose. + +```bash +docker pull hermeznetwork/zkevm-node +``` + +To orchestrate multiple deployments of the different ZKEVM Node components, a `docker-compose.yaml` file for Docker Compose can be used: + +```yaml + zkevm-aggregator: + container_name: zkevm-aggregator + image: zkevm-node + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --genesis /app/genesis.json --cfg /app/config.toml --components aggregator" +``` + +The container alone needs some parameters configured, access to certain configuration files and the appropriate ports exposed. + +- volumes: + - `your Account Keystore file`: /pk/keystore (note, this `/pk/keystore` value is the default path that's written in the Public Configuration files on this repo, meant to expedite deployments, it can be superseded via an env flag `ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH`.) + - `your config.toml file`: /app/config.toml + - `your genesis.json file`: /app/genesis.json + +- environment: Env variables that supersede the config file + - `ZKEVM_NODE_STATEDB_HOST`: Name of StateDB Database Host + +### The Account Keystore file: + +Since the Aggregator will send transactions to L1 you'll need to generate an account keystore: + +[Generate an Account Keystore file](./account_keystore.md) diff --git a/docs/components/databases.md b/docs/components/databases.md new file mode 100644 index 0000000000..117a73b10b --- /dev/null +++ b/docs/components/databases.md @@ -0,0 +1,57 @@ +# Component: Databases + +Different services rely on several standard PostgresQL databases, the most important one being the State Database. + +Configuring each DB is trivial if done with an orchestration tool such as Docker Compose. + +The following are examples on how one would provision each DB to serve along the components (rpc, aggregator, sequencer...) + +Note the `environment` values will change per DB. + +- **StateDB**: + +The StateDB needs to generate some extra databases and tables (`merkletree`) for use with the MerkleTree/Executor service. + +This is done via an sql file: [init_prover_db.sql](https://github.com/0xPolygonHermez/zkevm-node/blob/develop/db/scripts/init_prover_db.sql) + +```yaml +zkevm-state-db: + container_name: zkevm-state-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5432:5432 + volumes: + - ./init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql + environment: + - POSTGRES_USER=state_user + - POSTGRES_PASSWORD=state_password + - POSTGRES_DB=state_db + command: ["postgres", "-N", "500"] +``` + +- **Other DBs: Pool/RPC**: + +```yaml + zkevm-pool-db: + container_name: zkevm-pool-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5433:5432 + environment: + - POSTGRES_USER=pool_user + - POSTGRES_PASSWORD=pool_password + - POSTGRES_DB=pool_db + command: ["postgres", "-N", "500"] +``` diff --git a/docs/components/prover.md b/docs/components/prover.md new file mode 100644 index 0000000000..eedc0d088f --- /dev/null +++ b/docs/components/prover.md @@ -0,0 +1,39 @@ +# Component: Prover + +NOTE: The Prover is not considered part of the ZKEVM Node and all issues and suggestions should be sent to the [Prover repo](https://github.com/0xPolygonHermez/zkevm-prover/). + +## ZKEVM Prover: + +The ZKEVM Prover image hosts different components, *Merkle Tree*, *Executor* and finally the actual *Prover*. + +## Hard dependencies: + +- [Aggregator](./aggregator.md) + +## Running: + +The preferred way to run the ZKEVM Prover component is via Docker and Docker Compose. + +```bash +docker pull hermeznetwork/zkevm-prover +``` + +To orchestrate multiple deployments of the different ZKEVM Node components, a `docker-compose.yaml` file for Docker Compose can be used: + +```yaml + zkevm-prover: + container_name: zkevm-prover + image: zkevm-prover + volumes: + - ./prover-config.json:/usr/src/app/config.json + command: > + zkProver -c /usr/src/app/config.json +``` + +The `prover-config.json` file contents will vary depending on your use case, the main document explains different values to be changed to achieve different behaviors. + +### Ports: + +- `50051`: Prover +- `50061`: Merkle Tree +- `50071`: Executor \ No newline at end of file diff --git a/docs/components/rpc.md b/docs/components/rpc.md new file mode 100644 index 0000000000..3725ed0436 --- /dev/null +++ b/docs/components/rpc.md @@ -0,0 +1,45 @@ +# Component: RPC + +## ZKEVM RPC: + +The ZKEVM RPC relays transactions to the Trusted sequencer. + +## Hard dependencies: + +- [Synchronizer](./synchronizer.md) +- [StateDB Database](./databases.md) +- [RPCDB Database](./databases.md) +- [Merkle Tree and Executor](./prover.md) + +## Running: + +The preferred way to run the ZKEVM RPC component is via Docker and Docker Compose. + +```bash +docker pull hermeznetwork/zkevm-node +``` + +To orchestrate multiple deployments of the different ZKEVM Node components, a `docker-compose.yaml` file for Docker Compose can be used: + +```yaml + zkevm-rpc: + container_name: zkevm-rpc + image: zkevm-node + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --genesis /app/genesis.json --cfg /app/config.toml --components rpc" +``` + +The container alone needs some parameters configured, access to certain configuration files and the appropriate ports exposed. + +- ports: + - `8545:8545`: RPC Port + - `9091:9091`: Needed if Prometheus metrics are enabled +- environment: Env variables that supersede the config file + - `ZKEVM_NODE_STATEDB_HOST`: Name of StateDB Database Host + - `ZKEVM_NODE_POOL_HOST`: Name of PoolDB Database Host + - `ZKEVM_NODE_RPC_DB_HOST`: Name of RPCDB Database Host +- volumes: + - `your config.toml file`: /app/config.toml + - `your genesis file`: /app/genesis.json diff --git a/docs/components/sequencer.md b/docs/components/sequencer.md new file mode 100644 index 0000000000..3490494de7 --- /dev/null +++ b/docs/components/sequencer.md @@ -0,0 +1,37 @@ +# Component: Sequencer + +## ZKEVM Sequencer: + +The ZKEVM Sequencer is an optional but ancillary module that proposes new batches using transactions stored in the Pool Database. + +## Running: + +The preferred way to run the ZKEVM Sequencer component is via Docker and Docker Compose. + +```bash +docker pull hermeznetwork/zkevm-node +``` + +To orchestrate multiple deployments of the different ZKEVM Node components, a `docker-compose.yaml` file for Docker Compose can be used: + +```yaml + zkevm-sequencer: + container_name: zkevm-sequencer + image: zkevm-node + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --genesis /app/genesis.json --cfg /app/config.toml --components sequencer" +``` + +The container alone needs some parameters configured, access to certain configuration files and the appropriate ports exposed. + +- environment: Env variables that supersede the config file + - `ZKEVM_NODE_POOLDB_HOST`: Name of PoolDB Database Host + - `ZKEVM_NODE_STATEDB_HOST`: Name of StateDB Database Host +- volumes: + - `your Account Keystore file`: /pk/keystore (note, this `/pk/keystore` value is the default path that's written in the Public Configuration files on this repo, meant to expedite deployments, it can be superseded via an env flag `ZKEVM_NODE_ETHERMAN_PRIVATEKEYPATH`.) + - `your config.toml file`: /app/config.toml + - `your genesis.json file`: /app/genesis.json + +[How to generate an account keystore](./account_keystore.md) diff --git a/docs/components/synchronizer.md b/docs/components/synchronizer.md new file mode 100644 index 0000000000..0e79e52a37 --- /dev/null +++ b/docs/components/synchronizer.md @@ -0,0 +1,37 @@ +# Component: Synchronizer + +## ZKEVM Synchronizer: + +The ZKEVM Synchronizer is the **base** component for which all others will depend on. You can *mix and match* different components to achieve a different outcome, be it sending transactions or computing proofs, but the Sync module will need to be up and running. + +This module syncs data between the Layer 1 Ethereum network and ZKEVM L2 network. + +## Running: + +The preferred way to run the ZKEVM Synchronizer component is via Docker and Docker Compose. + +```bash +docker pull hermeznetwork/zkevm-node +``` + +To orchestrate multiple deployments of the different ZKEVM Node components, a `docker-compose.yaml` file for Docker Compose can be used: + +**THIS STEP IS MANDATORY ON ALL DEPLOYMENT MODES** + +```yaml + zkevm-sync: + container_name: zkevm-sync + image: zkevm-node + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --genesis /app/genesis.json --cfg /app/config.toml --components synchronizer" +``` + +The container alone needs some parameters configured, access to certain configuration files and the appropriate ports exposed. + +- environment: Env variables that supersede the config file + - `ZKEVM_NODE_STATEDB_HOST`: Name of StateDB Database Host +- volumes: + - `your config.toml file`: /app/config.toml + - `your genesis.json file`: /app/genesis.json diff --git a/docs/json-rpc-endpoints.md b/docs/json-rpc-endpoints.md new file mode 100644 index 0000000000..798ba49412 --- /dev/null +++ b/docs/json-rpc-endpoints.md @@ -0,0 +1,68 @@ +# JSON RPC Endpoints + +Here you will find the list of all supported JSON RPC endpoints and any differences between them in comparison to the default behavior of an ethereum node. + +If the endpoint is not in the list below, it means this specific endpoint is not supported yet, feel free to open an issue requesting it to be added and please explain the reason why you need it. + + +> Warning: debug endpoints are considered experimental as they have not been deeply tested yet +- `debug_traceBlockByHash` +- `debug_traceBlockByNumber` +- `debug_traceTransaction` + + +- `eth_blockNumber` +- `eth_call` + - _doesn't support state override at the moment and pending block. Will be implemented [#1990](https://github.com/0xPolygonHermez/zkevm-node/issues/1990)_ + - _doesn't support `from` values that are smart contract addresses. Will be implemented [#2017](https://github.com/0xPolygonHermez/zkevm-node/issues/2017)_ +- `eth_chainId` +- `eth_estimateGas` _* if the block number is set to pending we assume it is the latest_ +- `eth_gasPrice` +- `eth_getBalance` _* if the block number is set to pending we assume it is the latest_ +- `eth_getBlockByHash` +- `eth_getBlockByNumber` +- `eth_getBlockTransactionCountByHash` +- `eth_getBlockTransactionCountByNumber` +- `eth_getCode` _* if the block number is set to pending we assume it is the latest_ +- `eth_getCompilers` _* response is always empty_ +- `eth_getFilterChanges` +- `eth_getFilterLogs` +- `eth_getLogs` +- `eth_getStorageAt` _* if the block number is set to pending we assume it is the latest_ +- `eth_getTransactionByBlockHashAndIndex` +- `eth_getTransactionByBlockNumberAndIndex` _* if the block number is set to pending we assume it is the latest_ +- `eth_getTransactionByHash` +- `eth_getTransactionCount` +- `eth_getTransactionReceipt` _* doesn't include effectiveGasPrice. Will include once EIP1559 is implemented_ +- `eth_getUncleByBlockHashAndIndex` _* response is always empty_ +- `eth_getUncleByBlockNumberAndIndex` _* response is always empty_ +- `eth_getUncleCountByBlockHash` _* response is always zero_ +- `eth_getUncleCountByBlockNumber` _* response is always zero_ +- `eth_newBlockFilter` +- `eth_newFilter` +- `eth_protocolVersion` _* response is always zero_ +- `eth_sendRawTransaction` _* can relay TXs to another node_ +- `eth_subscribe` +- `eth_syncing` +- `eth_uninstallFilter` +- `eth_unsubscribe` + + +- `net_version` + + +- `txpool_content` _* response is always empty_ + + +- `web3_clientVersion` +- `web3_sha3` + + +- `zkevm_batchNumber` +- `zkevm_batchNumberByBlockNumber` +- `zkevm_consolidatedBlockNumber` +- `zkevm_getBatchByNumber` +- `zkevm_isBlockConsolidated` +- `zkevm_isBlockVirtualized` +- `zkevm_verifiedBatchNumber` +- `zkevm_virtualBatchNumber` diff --git a/docs/modes.md b/docs/modes.md new file mode 100644 index 0000000000..d14510dad8 --- /dev/null +++ b/docs/modes.md @@ -0,0 +1,102 @@ +# Configure the Node: Different modes of execution + +## JSON RPC Service: + +This service will sync transactions from L2 to L1, it does not require a Prover to be working, just an RPC and Synchronizer. + +### Services needed: + +*Please perform each of these steps (downloading and running) before continuing!* + +- [RPCDB and StateDB Database](./components/databases.md) +- [Synchronizer](./components/synchronizer.md) +- [RPC](./components/rpc.md) +- [MT and Executor](./components/prover.md) + +By default the config files found in the repository will spin up the Node in JSON RPC Service mode, which will not require a Prover (but will require a MT and Executor service). + +**This is considered to be the base, all modes require a Synchronizer Node container to be spun up* + +This will syncronize with the Trusted Sequencer (run by Polygon). + +Use the default [public config file](https://github.com/0xPolygonHermez/zkevm-node/blob/develop/config/environments/public/public.node.config.toml), and make sure the following values are set to: + +```toml +[RPC] +... +SequencerNodeURI = "https://public.zkevm-test.net:2083" +``` + +Same goes for the Prover Config ([prover-config.json](https://github.com/0xPolygonHermez/zkevm-node/blob/develop/config/environments/public/public.prover.config.json)): + +```json +{ + ... + "runProverServer": false, + "runProverServerMock": false, + "runProverClient": false, + "runExecutorServer": true, + "runExecutorClient": false, + "runStateDBServer": true +} +``` + +Additionally, the [`production-setup.md`](./production-setup.md) goes through the setup of both a synchronizer and RPC components of the node. + +### Docker services: + +- `zkevm-sync` +- `zkevm-prover` (`Merkle Tree`, `Executor`) +- `zkevm-rpc` +- Databases + +## If you want to create Proofs: + +This mode is a tad more complicated, as it will require more services and more machines: + +Requirements for the Prover service (sans MT/Executor): 1TB RAM 128 cores + +### Services needed: + +*Please perform each of these steps (downloading and running) before continuing!* + +- [StateDB Database](./components/databases.md) +- [Synchronizer](./components/synchronizer.md) +- [Aggregator](./components/aggregator.md) +- [Prover, MT and Executor](./components/prover.md) + +Machine 0: + +- Synchronizer +- Aggregator +- MT and Executor +- Databases + +Machine 1: + +- Prover only + +#### Machine 1 + +Use default [prover config](https://github.com/0xPolygonHermez/zkevm-node/blob/develop/config/environments/public/public.prover.config.json) but change the following values (`runProverServer` set to true, rest false): + +For *only* Prover Config (`only-prover-config.json`): + +```json +{ + ... + "runProverServer": true, + "runProverServerMock": false, + "runProverClient": false, + "runExecutorServer": false, + "runExecutorClient": false, + "runStateDBServer": false +} +``` + +### Docker services: + +- `zkevm-sync` +- `zkevm-prover` (`Prover`, `Merkle Tree`, `Executor`) +- `zkevm-aggregator` +- Databases \ No newline at end of file diff --git a/docs/networks.md b/docs/networks.md new file mode 100644 index 0000000000..d4ce7c907c --- /dev/null +++ b/docs/networks.md @@ -0,0 +1,5 @@ +# zkEVM testnet networks + +| Network Name | ChainID | RPC URL | Explorer | Bridge Info | +|--------------|---------|---------|----------|------------------| +| Public Testnet | `1402` | https://rpc.public.zkevm-test.net | https://explorer.public.zkevm-test.net | https://public.zkevm-test.net/ \ No newline at end of file diff --git a/docs/production-setup.md b/docs/production-setup.md index 6bcdca23cb..f2c373da72 100644 --- a/docs/production-setup.md +++ b/docs/production-setup.md @@ -1,339 +1,102 @@ -> WARNING: This documentation is outdated, it will be updated soon - # Production Setup -This document will guide you through all the steps needed to setup your own `zkEVM-Node` for production. - -## Network Components - -Required: +This guide describes how to run a node that: -- `Ethereum Node` - L1 Network -- `zkEVM-Node` - L2 Network - - `JSON RPC Server` - Interface to L2 network - - `Synchronizer` - Responsible to synchronize data between L1 and L2 - - `Sequencer` - Responsible to select transactions from the pool and propose new batches - - `Aggregator` - Responsible to consolidate the changes in the state proposed by the `Sequencers` -- `zk-Prover` - Zero knowledge proof generator +- Synchronizes the network +- Expose a JSON RPC interface, acting as an archive node -Optional: - -- `Metamask` - Wallet to manage blockchain accounts -- `Block Scout Explorer` - Web UI to interact with the network information +Note that sequencing and proving functionalities are not covered in this document **yet**. ## Requirements -- All components have docker images available on docker hub, so it's important that you have an account to download and use them, please check the links below for more details: - - [docker: Get-started](https://www.docker.com/get-started) - - [docker hub](https://hub.docker.com) - -Some of the images are still private, so make sure to login and check if you have access to the [Hermez organization](https://hub.docker.com/orgs/hermeznetwork) before trying to download them. Once you have docker installed on your machine, run the following command to login: - -```bash -docker login -``` - -- The examples on this document assume you have `docker-compose` installed, if you need help with the installation, please check the link below: - - [docker-compose: Install](https://docs.docker.com/compose/install/) - -## Recommendations - -- It's recommended that you create a directory to add the files we are going to create during this document, we are going to refer to this directory as `zkevm-node` directory. To create this directory, run the following command: - -```bash -mkdir -p /$HOME/zkevm-node -``` - -## Ethereum Node Setup - -Let's go! - -The first component we are going to setup is the Ethereum Node, it is the first because this is going to take a lot of time to synchronize the Ethereum network, so we will keep it synchronizing while we setup the others components to take advantage of this required time. - -Before we start: - -> There are many ways to setup an Ethereum L1 environment, we are going to use Geth for this. - -We recommend you to use a dedicated machine to this component, this can be shared by multiple zkEVM-Node if you want to have more than one in your infrastructure. - -First of all, we need to create a folder to store the Ethereum node data outside of the container, in order to not lose all the data if the container is restarted. - -```bash -mkdir -p /$HOME/zkevm-node/.ethereum -``` - -In order to run the Ethereum node instance, create a file called `docker-compose.yml` inside of the directory `zkevm-node` - -```dockercompose -version: '3' - -services: - - eth-node: - container_name: eth-node - image: ethereum/client-go:stable - ports: - - 8545:8545 - - 8546:8546 - - 30303:30303 - volumes: - - /$HOME/zkevm-node/.ethereum:/$HOME/geth/.ethereum - command: [ - "--goerli", - "--http", - "--http.addr=0.0.0.0", - "--http.corsdomain=*", - "--http.vhosts=*", - "--http.api=admin,eth,debug,miner,net,txpool,personal,web3", - "--ws", - "--ws.addr=0.0.0.0", - "--ws.origins=*", - "--graphql", - "--graphql.corsdomain=*", - "--graphql.vhosts=*", - "--vmdebug", - "--metrics", - "--datadir=/$HOME/geth/.ethereum" - ] -``` - -To run the Ethereum node instance, go to the `zkevm-node` directory in your terminal and run the following command: - -```bash -docker-compose up -d -``` - -If you want to follow the logs of the synchronization, run the following command: - -```bash -docker logs -f eth-node -``` - -## Postgres Setup - -Before we start: - -> It's important to say that running the instance of Postgres in a docker container is just one way of running it. We strongly recommend you to have a specialized infrastructure to the DB like AWS RDS, a On-site server or any other Postgres DB dedicated infrastructure. - -Also: - -> It's not required to have a backup, since all the data is available on L1 to be resynchronized if it was lost, but it's strongly recommended to have a backup in order to avoid resynchronizing the whole network in case of a problem with the db, because the synchronization is a process that can take a lot of time and this time is going to ever increase as the network continues to roll. - -With that said, we must setup a Postgres instance to be shared between the Node and the Prover. - -- Node requires a full access user to run the migrations and control the data. -- Prover only needs a readonly user to access the Merkletree data and compute the proofs. - -We need to create a folder to store the Postgres data outside of the container, in order to not lose all the data if the container is restarted. +- A machine to run the zkEVM node with the following requirements: + - Hardware: 32G RAM, 4 cores, 128G Disk with high IOPS (as the network is super young the current disk requirements are quite low, but they will increase overtime. Also note that this requirement is true if the DBs run on the same machine, but it's recommended to run Postgres on dedicated infra). Currently ARM-based CPUs are not supported + - Software: Ubuntu 22.04, Docker +- A L1 node: we recommend using geth, but what it's actually needed is access to a JSON RPC interface for the L1 network (Goerli for zkEVM testnet, Ethereum mainnet for zkEVM mainnet) -```bash -mkdir -p /$HOME/zkevm-node/.postgres -``` - -In order to run the Postgres instance, create a file called `docker-compose.yml` inside of the directory `zkevm-node` - -> We recommend you to customize the ENVIRONMENT variables values in the file below to your preference: - -```docker-compose -version: '3' - -services: +## Setup - zkevm-db: - container_name: zkevm-db - image: postgres - ports: - - 5432:5432 - environment: - - POSTGRES_USER=test_user - - POSTGRES_PASSWORD=test_password - - POSTGRES_DB=test_db - volumes: - - /$HOME/zkevm-node/.postgres:./postgres-data -``` +This is the most straightforward path to run a zkEVM node, and it's perfectly fine for most use cases, however if you are interested in providing service to many users it's recommended to do some tweaking over the default configuration. Furthermore, this is quite opinionated, feel free to run this software in a different way, for instance it's not needed to use Docker, you could use the Go and C++ binaries directly. -To run the postgres instance, go to the `zkevm-node` directory in your terminal and run the following command: +tl;dr: ```bash -docker-compose up -d -``` - -Congratulations, your postgres instance is ready! - -## Prover Setup - -Before we start: - -> It's very important to say that the Prover is a software that requires a lot of technology power to be executed properly, with that said, we recommend you to have a dedicated machine with the following configuration to run the prover: +# DOWNLOAD ARTIFACTS +ZKEVM_NET=mainnet +ZKEVM_DIR=./path/to/install # CHANGE THIS +ZKEVM_CONFIG_DIR=./path/to/config # CHANGE THIS +curl -L https://github.com/0xPolygonHermez/zkevm-node/releases/latest/download/$ZKEVM_NET.zip > $ZKEVM_NET.zip && unzip -o $ZKEVM_NET.zip -d $ZKEVM_DIR && rm $ZKEVM_NET.zip +cp $ZKEVM_DIR/$ZKEVM_NET/example.env $ZKEVM_CONFIG_DIR/.env -- TBD -- TBD -- TBD -- TBD +# EDIT THIS env file: +nano $ZKEVM_CONFIG_DIR/.env -Also: - -> The prover depends on the Postgres instance we created before, so make sure it has network access to this. - -- TDB how to setup de prover, docker, downloads, dependencies, etc - -## zkEVM-Node Setup - -Very well, we already have the Postgres, Prover and Ethereum Node instances running, now it's time so setup the zkEVM-Node. - -> The node depends on the Postgres, Prover and Ethereum Node instances, so make sure it has network access to them. We also expect the node to have its own dedicated machine - -Before we start, the node requires an Ethereum account with: - -- Funds on L1 in order to propose new batches and consolidate the state -- Tokens to pay the collateral for batch proposal -- Approval of these tokens to be used by the roll-up SC on behalf of the Ethereum account owner -- Register this account as a sequencer - -The node expected to read a `keystore` file, which is an encrypted file containing your credentials. -To create this file, go to the `zkevm-node` directory and run the following command: - -> Remember to replace the `--pk` and `--pw` parameter values by the L1 account private key and the password you want to use to encrypt the file, the password will be required in the future to configure the node, so make sure you will remember it. - -```bash -docker run --rm hermeznetwork/zkevm-node:latest sh -c "/app/zkevm-node encryptKey --pk= --pw= --output=./keystore; cat ./keystore/*" > acc.keystore +# RUN: +docker compose --env-file $ZKEVM_CONFIG_DIR/.env -f $ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml up -d ``` -The command above will create the file `acc.keystore` inside of the `zkevm-node` directory. +Explained step by step: -After it we need to create a configuration file to provide the configurations to the node, to achieve this create a file called `config.toml` inside of the `zkevm-node` directory, then go to the example [config file](config/config.debug.toml) and `copy/paste` the content into the `config.toml` you'll actually use. +1. Define network: `ZKEVM_NET=testnet` or `ZKEVM_NET=mainnet` +2. Define installation path: `ZKEVM_DIR=./path/to/install` +3. Define a config directory: `ZKEVM_CONFIG_DIR=./path/to/config` +4. It's recommended to source this env vars in your `~/.bashrc`, `~/.zshrc` or whatever you're using +5. Download and extract the artifacts: `curl -L https://github.com/0xPolygonHermez/zkevm-node/releases/latest/download/$ZKEVM_NET.zip > $ZKEVM_NET.zip && unzip -o $ZKEVM_NET.zip -d $ZKEVM_DIR && rm $ZKEVM_NET.zip`. Note you may need to install `unzip` for this command to work +6. Copy the file with the env parameters: `cp $ZKEVM_DIR/$ZKEVM_NET/example.env $ZKEVM_CONFIG_DIR/.env` +7. Edit the env file, with your favourite editor. The example will use nano: `nano $ZKEVM_CONFIG_DIR/.env`. This file contains the configuration that anyone should modify. For advanced configuration: + 1. Copy the config files into the config directory `cp $ZKEVM_DIR/$ZKEVM_NET/config/environments/public/* $ZKEVM_CONFIG_DIR/` + 2. Make sure the modify the `ZKEVM_ADVANCED_CONFIG_DIR` from `$ZKEVM_CONFIG_DIR/.env` with the correct path + 3. Edit the different configuration files +8. Run the node: `docker compose --env-file $ZKEVM_CONFIG_DIR/.env -f $ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml up -d`. You may need to run this command using `sudo` depending on your Docker setup. +9. Make sure that all components are running: `docker compose --env-file $ZKEVM_CONFIG_DIR/.env -f $ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml ps`. You should see the following containers: + 1. zkevm-rpc + 2. zkevm-sync + 3. zkevm-state-db + 4. zkevm-pool-db + 5. zkevm-prover -Remember to: +If everything has gone as expected you should be able to run queries to the JSON RPC at `http://localhost:8545`. For instance you can run the following query that fetches the latest synchronized L2 block, if you call this every few seconds, you should see the number increasing: -- replace the database information if you set it differently while setting up the Postgres instance -- set the `Database Host` with the `Postgres instance IP` -- set the `Etherman URL` with the `JSON RPC URL` of the `Ethereum node` -- set the `Etherman Password` to allow the node to decrypt the `keystore file` -- set the `Prover URI` the `IP and port` of the `Prover Instance` +`curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' http://localhost:8545` +## Troubleshooting +- It's possible that the machine you're using already uses some of the necessary ports. In this case you can change them directly at `$ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml` +- If one or more containers are crashing please check the logs using `docker compose --env-file $ZKEVM_CONFIG_DIR/.env -f $ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml logs ` -In order to be able to propose batches we are going to register our Ethereum account as a Sequencer, -to do this execute this command: +## Stop ```bash -docker run --rm -v /$HOME/zkevm-node/config.toml:/app/config.toml hermeznetwork/zkevm-node:latest sh -c "./zkevm-node register --cfg=/app/config.toml --network=internaltestnet --y " +docker compose --env-file $ZKEVM_CONFIG_DIR/.env -f $ZKEVM_DIR/$ZKEVM_NET/docker-compose.yml down ``` -In order to propose new batches, you must approve the Tokens to be used by the Roll-up on your behalf, to do this execute this command: -> remember to set the value of the parameter amount before executing +## Updating -```bash -docker run --rm -v /$HOME/zkevm-node/config.toml:/app/config.toml hermeznetwork/zkevm-node:latest sh -c "./zkevm-node approve --cfg=/app/config.toml --network=internaltestnet --address=poe --amount=0 --y" -``` - -Now we are going to put everything together in order to run the `zkEVM-Node` instance. - -Create a file called `docker-compose.yml` inside of the directory `zkevm-node`. - -```docker-compose -version: '3' - -services: - - zkevm-node: - container_name: zkevm-node - image: zkevm-node - ports: - - 8545:8545 - volumes: - - /$HOME/zkevm-node/acc/keystore:/pk/keystore - - /$HOME/zkevm-node/config.toml:/app/config.toml - command: ["./zkevm-node", "run", "--network", "internaltestnet", "--cfg", "/app/config.toml"] -``` - -To run the `zkEVM-Node` instance, go to the `zkevm-node` directory in your terminal and run the following command: - -```bash -docker-compose up -d -``` +In order to update the software, you have to repeat the steps of the setup, but taking care of not overriding the config that you have modified. Basically, instead of running `cp $ZKEVM_DIR/$ZKEVM_NET/example.env $ZKEVM_CONFIG_DIR/.env`, check if the variables of `$ZKEVM_DIR/$ZKEVM_NET/example.env` have been renamed or there are new ones, and update `$ZKEVM_CONFIG_DIR/.env` accordingly. -## Setup Explorer +## Advanced setup -To have a visual access to the network we are going to setup a Block Scout instance. +> DISCLAIMER: right now this part of the documentation attempts to give ideas on how to improve the setup for better performance, but is far from being a detailed guide on how to achieve this. Please open issues requesting more details if you don't understand how to achieve something. We will keep improving this doc for sure! -For more details about Block Scout, check it here: +There are some fundamental changes that can be done towards the basic setup, in order to get better performance and scale better: -Block Scout requires access to the `zkEVM-Node` instance to have access to the network -via the JSON RPC Server and a dedicated Postgres Instance in order to save its own data. +### DB -We recommend you use a dedicated machine for the Explorer. - -Create a file called `docker-compose.yml` inside of the `zkevm-node` directory. - -> Feel free to customize the environment variables to set the user, password and -> database for the Explore Postgres instance, but make sure to also update the url to connect -> to the DB in the Explorer environment variable called DATABASE_URL -> Remember to set the environment variable ETHEREUM_JSONRPC_HTTP_URL with the `zkEVM-Node` IP and PORT - -```docker-compose -version: '3' - -services: - - zkevm-explorer-db: - container_name: zkevm-explorer-db - image: postgres - ports: - - 5432:5432 - environment: - - POSTGRES_USER=test_user - - POSTGRES_PASSWORD=test_password - - POSTGRES_DB=explorer - - zkevm-explorer: - container_name: zkevm-explorer - image: hermeznetwork/hermez-node-blockscout:latest - ports: - - 4000:4000 - environment: - - NETWORK=POE - - SUBNETWORK=Polygon Hermez - - COIN=ETH - - ETHEREUM_JSONRPC_VARIANT=geth - - ETHEREUM_JSONRPC_HTTP_URL=http://:8545 # Set the IP and PORT of the zkEVM-Node - - DATABASE_URL=postgres://test_user:test_password@zkevm-explorer-db:5432/explorer - - ECTO_USE_SSL=false - - MIX_ENV=prod - - LOGO=/images/blockscout_logo.svg - - LOGO_FOOTER=/images/blockscout_logo.svg - command: ["/bin/sh", "-c", "mix do ecto.create, ecto.migrate; mix phx.server"] -``` - -To run the Explorer, execute the following command: - -```bash -docker-compose up -d zkevm-explorer-db -sleep5 -docker-compose up -d zkevm-explorer -``` +In the basic setup, there are Postgres being instanciated as Docker containers. For better performance is recommended to: -## Setup Metamask +- Run dedicated instances for Postgres. To achieve this you will need to: + - Remove the Postgres services (`zkevm-pool-db` and `zkevm-state-db`) from the `docker-compose.yml` + - Instantiate Postgres elsewhere (note that you will have to create credentials and run some queries to make this work, following the config files and docker-compose should give a clear idea of what to do) + - Update the `public.node.config.toml` to use the correct URI for both DBs + - Update `prover.public.config.json` to use the correct URI for the state DB +- Use a setup of Postgres that allows to have separated endpoints for read / write replicas -To be able to use the Network via Metamask, a custom network must be configured. +### JSON RPC -> IMPORTANT: Metamask only allows custom networks to be added if the network is -> up and running, so make sure the whole environment is up and running before -> trying to add it as a custom network +Unlike the synchronizer, that needs to have only one instance running (having more than one synchronizer running at the same time connected to the same DB can be fatal), the JSON RPC can scale horizontally. -To configure a custom network follow these steps: +There can be as many instances of it as needed, but in order to not introduce other bottlenecks, it's important to consider the following: -1. Login to you Metamask account -2. Click in the circle with a picture on the top right side to open the Menu -3. Click on Settings -4. On the Left menu click com Networks -5. Fill up the following fields: - 1. Network Name: Polygon Hermez - Goerli - 2. New RPC URL: - 3. Chain ID: TBD - 4. Currency Symbol: ETH - 5. Block Explorer URL: -6. Click on Save -7. Click on the X in the right top corner to close the Settings -8. Click in the list of networks on the top right corner -9. Select Polygon Hermez - Goerli +- Read replicas of the State DB should be used +- Synchronizer should have an exclusive instance of `zkevm-prover` +- JSON RPCs should scale in correlation with instances of `zkevm-prover`. The most obvious way to do so is by having a dedicated `zkevm-prover` for each `zkevm-rpc`. But depending on the payload of your solution it could be worth to have `1 zkevm-rpc : many zkevm-prover` or `many zkevm-rpc : 1 zkevm-prover`, ... For reference, the `zkevm-prover` implements the EVM, and therefore will be heavily used when calling endpoints such as `eth_call`. On the other hand, there are other endpoints that relay on the `zkevm-state-db` diff --git a/docs/running_local.md b/docs/running_local.md index c6614914f2..640b7a1f22 100644 --- a/docs/running_local.md +++ b/docs/running_local.md @@ -1,21 +1,23 @@ -> WARNING: This documentation is outdated, it will be updated soon +# Steps to run/develop on the environment locally -# Steps to run environment locally +# Warning: + +>Currently the Executor/Prover does not run on ARM-powered Macs. For Windows users, WSL/WSL2 use is not recommended. ## Overview This documentation will help you running the following components: -- zkEVM Node Database -- Explorer Database +- zkEVM Node Databases +- Explorer Databases - L1 Network - Prover -- zkEVM Node -- Explorer +- zkEVM Node components +- Explorers ## Requirements -The current version of the environment requires `go`, `docker` and `docker-compose` to be previously installed, check the links bellow to understand how to install them: +The current version of the environment requires `go`, `docker` and `docker-compose` to be previously installed, check the links below to understand how to install them: - - @@ -28,12 +30,26 @@ If you haven't build the `zkevm-node` image yet, you must run: make build-docker ``` +## A look at how the binary works: + +The `zkevm-node` allows certain commands to interact with smart contracts, run certain components, create encryption files and print out debug information. + +To interact with the binary program we provide docker compose files, and a Makefile to spin up/down the different services and components, ensuring a smooth deployment locally and better interface in command line for developers. + ## Controlling the environment > All the data is stored inside of each docker container, this means once you remove the container, the data will be lost. To run the environment: +The `test/` directory contains scripts and files for developing and debugging. + +```bash +cd test/ +``` + +Then: + ```bash make run ``` @@ -56,63 +72,96 @@ The `make run` will execute the containers needed to run the environment but thi If you need sample data already deployed to the network, we have the following scripts: -First initialize the network for the L2 node: +**To add some examples of transactions and smart contracts:** ```bash -make init-network +make deploy-sc ``` -To add some examples of transactions and smart contracts: +**To deploy a full a uniswap environment:** ```bash -make deploy-sc +make deploy-uniswap ``` -To deploy a full a uniswap environment: +**To grant the Matic smart contract a set amount of tokens, run:** ```bash -make deploy-uniswap +make run-approve-matic ``` ## Accessing the environment -- zkEVM Node Database - - `Type:` Postgres DB - - `User:` test_user - - `Password:` test_password - - `Database:` test_db - - `Host:` localhost - - `Port:` 5432 - - `Url:` -- Explorer Database - - `Type:` Postgres DB - - `User:` test_user - - `Password:` test_password - - `Database:` explorer - - `Host:` localhost - - `Port:` 5433 - - `Url:` -- L1 Network - - `Type:` Geth - - `Host:` localhost - - `Port:` 8545 - - `Url:` +- **Databases**: + - zkEVM Node *State* Database + - `Type:` Postgres DB + - `User:` state_user + - `Password:` state_password + - `Database:` state-db + - `Host:` localhost + - `Port:` 5432 + - `Url:` + - zkEVM Node *Pool* Database + - `Type:` Postgres DB + - `User:` pool_user + - `Password:` pool_password + - `Database:` pool_db + - `Host:` localhost + - `Port:` 5433 + - `Url:` + - zkEVM Node *JSON-RPC* Database + - `Type:` Postgres DB + - `User:` rpc_user + - `Password:` rpc_password + - `Database:` rpc_db + - `Host:` localhost + - `Port:` 5434 + - `Url:` + - Explorer L1 Database + - `Type:` Postgres DB + - `User:` l1_explorer_user + - `Password:` l1_explorer_password + - `Database:` l1_explorer_db + - `Host:` localhost + - `Port:` 5435 + - `Url:` + - Explorer L2 Database + - `Type:` Postgres DB + - `User:` l2_explorer_user + - `Password:` l2_explorer_password + - `Database:` l2_explorer_db + - `Host:` localhost + - `Port:` 5436 + - `Url:` +- **Networks**: + - L1 Network + - `Type:` Geth + - `Host:` localhost + - `Port:` 8545 + - `Url:` + - zkEVM Node + - `Type:` JSON RPC + - `Host:` localhost + - `Port:` 8123 + - `Url:` +- **Explorers**: + - Explorer L1 + - `Type:` Web + - `Host:` localhost + - `Port:` 4000 + - `Url:` + - Explorer L2 + - `Type:` Web + - `Host:` localhost + - `Port:` 4001 + - `Url:` - Prover - `Type:` Mock - `Host:` localhost - - `Port:` 50001 + - `Port:` Depending on the prover image, if it's mock or not: + - Prod prover: 50052 for Prover, 50061 for Merkle Tree, 50071 for Executor + - Mock prover: 43061 for MT, 43071 for Executor - `Url:` -- zkEVM Node - - `Type:` JSON RPC - - `Host:` localhost - - `Port:` 8123 - - `Url:` -- Explorer - - `Type:` Web - - `Host:` localhost - - `Port:` 4000 - - `Url:` - ## Metamask > Metamask requires the network to be running while configuring it, so make sure your network is running before starting. @@ -124,9 +173,9 @@ To configure your Metamask to use your local environment, follow these steps: 3. On the left menu, click on Networks 4. Click on `Add Network` button 5. Fill up the L2 network information - 1. `Network Name:` Polygon Hermez - Local + 1. `Network Name:` Polygon zkEVM - Local 2. `New RPC URL:` - 3. `ChainID:` 1000 + 3. `ChainID:` 1001 4. `Currency Symbol:` ETH 5. `Block Explorer URL:` 6. Click on Save @@ -142,10 +191,10 @@ To configure your Metamask to use your local environment, follow these steps: | Address | Description | |---|---| -| 0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 | Proof of Efficiency | -| 0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 | Bridge | +| 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 | Proof of Efficiency | +| 0xff0EE8ea08cEf5cb4322777F5CC3E8A584B8A4A0 | Bridge | | 0x5FbDB2315678afecb367f032d93F642f64180aa3 | Matic token | -| 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 | GlobalExitRootManager | +| 0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6 | GlobalExitRootManager | ## Deployer Account diff --git a/docs/zkEVM-custom-endpoints.md b/docs/zkEVM-custom-endpoints.md new file mode 100644 index 0000000000..ef496c1df5 --- /dev/null +++ b/docs/zkEVM-custom-endpoints.md @@ -0,0 +1,9 @@ +# zkEVM custom endpoints + +The zkEVM Node JSON RPC server works as is when compared to the official Ethereum JSON RPC, but there are some extra information that also needs to be shared when talking about a L2 Networks, in our case we have information about Batches, Proofs, L1 transactions and much more + +In order to allow users to consume this information, a custom set of endpoints were created to provide this information, they are provided under the prefix `zkevm_` + +The endpoint documentation follows the [OpenRPC Specification](https://spec.open-rpc.org/) and can be found next to the endpoints implementation as a json file, [here](../jsonrpc/endpoints_zkevm.openrpc.json) + +The spec can be easily visualized using the oficial [OpenRPC Playground](https://playground.open-rpc.org/), just copy and paste the json content into the playground area to find a friendly UI showing the methods diff --git a/encoding/encoding.go b/encoding/encoding.go index 6e1472cacc..9bcb9d31e8 100644 --- a/encoding/encoding.go +++ b/encoding/encoding.go @@ -13,12 +13,10 @@ import ( const ( // Base10 decimal base Base10 = 10 - // Base16 hexadecimal base - Base16 = 16 - // BitSize64 64 bits - BitSize64 = 64 // TenToThePowerOf18 represents 1000000000000000000 TenToThePowerOf18 = 1000000000000000000 + // Gwei represents 1000000000 wei + Gwei = 1000000000 // MaxUint256StrNumber represents 2**256 -1 as string MaxUint256StrNumber = "115792089237316195423570985008687907853269984665640564039457584007913129639935" ) @@ -35,7 +33,7 @@ func DecodeUint64orHex(val *string) (uint64, error) { str = str[2:] base = 16 } - return strconv.ParseUint(str, base, BitSize64) + return strconv.ParseUint(str, base, hex.BitSize64) } // DecodeUint256orHex decodes a string uint256 or hex string into a bit.Int diff --git a/etherman/config.go b/etherman/config.go index fec6a62e59..b91e4948f7 100644 --- a/etherman/config.go +++ b/etherman/config.go @@ -1,9 +1,16 @@ package etherman +import ( + "github.com/0xPolygonHermez/zkevm-node/etherman/etherscan" +) + // Config represents the configuration of the etherman type Config struct { URL string `mapstructure:"URL"` PrivateKeyPath string `mapstructure:"PrivateKeyPath"` PrivateKeyPassword string `mapstructure:"PrivateKeyPassword"` + + MultiGasProvider bool `mapstructure:"MultiGasProvider"` + Etherscan etherscan.Config } diff --git a/etherman/converters.go b/etherman/converters.go deleted file mode 100644 index 7ff0660da4..0000000000 --- a/etherman/converters.go +++ /dev/null @@ -1,65 +0,0 @@ -package etherman - -import ( - "fmt" - "math/big" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" -) - -const ( - minProofLen = 2 - maxProofLen = 3 -) - -func stringToFixedByteArray(str string) ([32]byte, error) { - var res [32]byte - data, err := hex.DecodeHex(str) - if err != nil { - return [32]byte{}, err - } - copy(res[:], data) - return res, nil -} - -func strSliceToBigIntArray(data []string) ([2]*big.Int, error) { - if len(data) < minProofLen || len(data) > maxProofLen { - return [2]*big.Int{}, fmt.Errorf("wrong slice length, current %d, expected between %d or %d", len(data), minProofLen, maxProofLen) - } - var res [2]*big.Int - for i, v := range data { - if i < minProofLen { - bigInt, ok := new(big.Int).SetString(v, encoding.Base10) - if !ok { - return [2]*big.Int{}, fmt.Errorf("failed to convert string to big int, str: %s", v) - } - res[i] = bigInt - } - } - return res, nil -} - -func proofSlcToIntArray(proofs []*pb.ProofB) ([2][2]*big.Int, error) { - if len(proofs) < minProofLen || len(proofs) > maxProofLen { - return [2][2]*big.Int{}, fmt.Errorf("wrong slice length, current %d, expected between %d or %d", len(proofs), minProofLen, maxProofLen) - } - - var res [2][2]*big.Int - for i, v := range proofs { - if i < minProofLen { - for j, b := range proofs[i].Proofs { - if j < minProofLen { - bigInt, ok := new(big.Int).SetString(b, encoding.Base10) - if !ok { - return [2][2]*big.Int{}, fmt.Errorf("failed to convert string to big int, str: %s", v) - } - res[i][1-j] = bigInt - } - } - } - } - - return res, nil -} diff --git a/etherman/errors.go b/etherman/errors.go new file mode 100644 index 0000000000..d98bce5151 --- /dev/null +++ b/etherman/errors.go @@ -0,0 +1,48 @@ +package etherman + +import ( + "errors" + "strings" +) + +var ( + // ErrGasRequiredExceedsAllowance gas required exceeds the allowance + ErrGasRequiredExceedsAllowance = errors.New("gas required exceeds allowance") + // ErrContentLengthTooLarge content length is too large + ErrContentLengthTooLarge = errors.New("content length too large") + //ErrTimestampMustBeInsideRange Timestamp must be inside range + ErrTimestampMustBeInsideRange = errors.New("timestamp must be inside range") + //ErrInsufficientAllowance insufficient allowance + ErrInsufficientAllowance = errors.New("insufficient allowance") + // ErrBothGasPriceAndMaxFeeGasAreSpecified both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified + ErrBothGasPriceAndMaxFeeGasAreSpecified = errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + // ErrMaxFeeGasAreSpecifiedButLondonNotActive maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet + ErrMaxFeeGasAreSpecifiedButLondonNotActive = errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet") + // ErrNoSigner no signer to authorize the transaction with + ErrNoSigner = errors.New("no signer to authorize the transaction with") + // ErrMissingTrieNode means that a node is missing on the trie + ErrMissingTrieNode = errors.New("missing trie node") + + errorsCache = map[string]error{ + ErrGasRequiredExceedsAllowance.Error(): ErrGasRequiredExceedsAllowance, + ErrContentLengthTooLarge.Error(): ErrContentLengthTooLarge, + ErrTimestampMustBeInsideRange.Error(): ErrTimestampMustBeInsideRange, + ErrInsufficientAllowance.Error(): ErrInsufficientAllowance, + ErrBothGasPriceAndMaxFeeGasAreSpecified.Error(): ErrBothGasPriceAndMaxFeeGasAreSpecified, + ErrMaxFeeGasAreSpecifiedButLondonNotActive.Error(): ErrMaxFeeGasAreSpecifiedButLondonNotActive, + ErrNoSigner.Error(): ErrNoSigner, + ErrMissingTrieNode.Error(): ErrMissingTrieNode, + } +) + +func tryParseError(err error) (error, bool) { + parsedError, exists := errorsCache[err.Error()] + if !exists { + for errStr, actualErr := range errorsCache { + if strings.Contains(err.Error(), errStr) { + return actualErr, true + } + } + } + return parsedError, exists +} diff --git a/etherman/errors_test.go b/etherman/errors_test.go new file mode 100644 index 0000000000..186768e6b1 --- /dev/null +++ b/etherman/errors_test.go @@ -0,0 +1,37 @@ +package etherman + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTryParseWithExactMatch(t *testing.T) { + expected := ErrTimestampMustBeInsideRange + smartContractErr := expected + + actualErr, ok := tryParseError(smartContractErr) + + assert.ErrorIs(t, actualErr, expected) + assert.True(t, ok) +} + +func TestTryParseWithContains(t *testing.T) { + expected := ErrTimestampMustBeInsideRange + smartContractErr := fmt.Errorf(" execution reverted: ProofOfEfficiency::sequenceBatches: %s", expected) + + actualErr, ok := tryParseError(smartContractErr) + + assert.ErrorIs(t, actualErr, expected) + assert.True(t, ok) +} + +func TestTryParseWithNonExistingErr(t *testing.T) { + smartContractErr := fmt.Errorf("some non-existing err") + + actualErr, ok := tryParseError(smartContractErr) + + assert.Nil(t, actualErr) + assert.False(t, ok) +} diff --git a/etherman/etherman.go b/etherman/etherman.go index 2a2e82f851..cec1edf505 100644 --- a/etherman/etherman.go +++ b/etherman/etherman.go @@ -5,22 +5,29 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" + "os" + "path/filepath" "strings" "time" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/globalexitrootmanager" + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/etherman/etherscan" + "github.com/0xPolygonHermez/zkevm-node/etherman/ethgasstation" "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/matic" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmglobalexitroot" ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/test/operations" "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/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/crypto" "github.com/ethereum/go-ethereum/ethclient" @@ -28,15 +35,30 @@ import ( ) var ( - updateGlobalExitRootSignatureHash = crypto.Keccak256Hash([]byte("UpdateGlobalExitRoot(uint256,bytes32,bytes32)")) - forcedBatchSignatureHash = crypto.Keccak256Hash([]byte("ForceBatch(uint64,bytes32,address,bytes)")) - sequencedBatchesEventSignatureHash = crypto.Keccak256Hash([]byte("SequenceBatches(uint64)")) - forceSequencedBatchesSignatureHash = crypto.Keccak256Hash([]byte("SequenceForceBatches(uint64)")) - verifiedBatchSignatureHash = crypto.Keccak256Hash([]byte("VerifyBatch(uint64,address)")) - setTrustedSequencerURLSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedSequencerURL(string)")) - setForceBatchAllowedSignatureHash = crypto.Keccak256Hash([]byte("SetForceBatchAllowed(bool)")) - setTrustedSequencerSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedSequencer(address)")) - transferOwnershipSignatureHash = crypto.Keccak256Hash([]byte("OwnershipTransferred(address,address)")) + updateGlobalExitRootSignatureHash = crypto.Keccak256Hash([]byte("UpdateGlobalExitRoot(bytes32,bytes32)")) + forcedBatchSignatureHash = crypto.Keccak256Hash([]byte("ForceBatch(uint64,bytes32,address,bytes)")) + sequencedBatchesEventSignatureHash = crypto.Keccak256Hash([]byte("SequenceBatches(uint64)")) + forceSequencedBatchesSignatureHash = crypto.Keccak256Hash([]byte("SequenceForceBatches(uint64)")) + verifyBatchesSignatureHash = crypto.Keccak256Hash([]byte("VerifyBatches(uint64,bytes32,address)")) + verifyBatchesTrustedAggregatorSignatureHash = crypto.Keccak256Hash([]byte("VerifyBatchesTrustedAggregator(uint64,bytes32,address)")) + setTrustedSequencerURLSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedSequencerURL(string)")) + setTrustedSequencerSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedSequencer(address)")) + transferOwnershipSignatureHash = crypto.Keccak256Hash([]byte("OwnershipTransferred(address,address)")) + emergencyStateActivatedSignatureHash = crypto.Keccak256Hash([]byte("EmergencyStateActivated()")) + emergencyStateDeactivatedSignatureHash = crypto.Keccak256Hash([]byte("EmergencyStateDeactivated()")) + updateZkEVMVersionSignatureHash = crypto.Keccak256Hash([]byte("UpdateZkEVMVersion(uint64,uint64,string)")) + consolidatePendingStateSignatureHash = crypto.Keccak256Hash([]byte("ConsolidatePendingState(uint64,bytes32,uint64)")) + setTrustedAggregatorTimeoutSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedAggregatorTimeout(uint64)")) + setTrustedAggregatorSignatureHash = crypto.Keccak256Hash([]byte("SetTrustedAggregator(address)")) + setPendingStateTimeoutSignatureHash = crypto.Keccak256Hash([]byte("SetPendingStateTimeout(uint64)")) + setMultiplierBatchFeeSignatureHash = crypto.Keccak256Hash([]byte("SetMultiplierBatchFee(uint16)")) + setVerifyBatchTimeTargetSignatureHash = crypto.Keccak256Hash([]byte("SetVerifyBatchTimeTarget(uint64)")) + setForceBatchTimeoutSignatureHash = crypto.Keccak256Hash([]byte("SetForceBatchTimeout(uint64)")) + activateForceBatchesSignatureHash = crypto.Keccak256Hash([]byte("ActivateForceBatches()")) + transferAdminRoleSignatureHash = crypto.Keccak256Hash([]byte("TransferAdminRole(address)")) + acceptAdminRoleSignatureHash = crypto.Keccak256Hash([]byte("AcceptAdminRole(address)")) + proveNonDeterministicPendingStateSignatureHash = crypto.Keccak256Hash([]byte("ProveNonDeterministicPendingState(bytes32,bytes32)")) + overridePendingStateSignatureHash = crypto.Keccak256Hash([]byte("OverridePendingState(uint64,bytes32,address)")) // Proxy events initializedSignatureHash = crypto.Keccak256Hash([]byte("Initialized(uint8)")) @@ -45,9 +67,20 @@ var ( upgradedSignatureHash = crypto.Keccak256Hash([]byte("Upgraded(address)")) // ErrNotFound is used when the object is not found - ErrNotFound = errors.New("Not found") + ErrNotFound = errors.New("not found") + // ErrIsReadOnlyMode is used when the EtherMan client is in read-only mode. + ErrIsReadOnlyMode = errors.New("etherman client in read-only mode: no account configured to send transactions to L1. " + + "please check the [Etherman] PrivateKeyPath and PrivateKeyPassword configuration") + // ErrPrivateKeyNotFound used when the provided sender does not have a private key registered to be used + ErrPrivateKeyNotFound = errors.New("can't find sender private key to sign tx") ) +// SequencedBatchesSigHash returns the hash for the `SequenceBatches` event. +func SequencedBatchesSigHash() common.Hash { return sequencedBatchesEventSignatureHash } + +// TrustedVerifyBatchesSigHash returns the hash for the `TrustedVerifyBatches` event. +func TrustedVerifyBatchesSigHash() common.Hash { return verifyBatchesTrustedAggregatorSignatureHash } + // EventOrder is the the type used to identify the events order type EventOrder string @@ -58,32 +91,56 @@ const ( SequenceBatchesOrder EventOrder = "SequenceBatches" // ForcedBatchesOrder identifies a ForcedBatches event ForcedBatchesOrder EventOrder = "ForcedBatches" - // VerifyBatchOrder identifies a VerifyBatch event - VerifyBatchOrder EventOrder = "VerifyBatch" + // TrustedVerifyBatchOrder identifies a TrustedVerifyBatch event + TrustedVerifyBatchOrder EventOrder = "TrustedVerifyBatch" // SequenceForceBatchesOrder identifies a SequenceForceBatches event SequenceForceBatchesOrder EventOrder = "SequenceForceBatches" + // ForkIDsOrder identifies an updateZkevmVersion event + ForkIDsOrder EventOrder = "forkIDs" ) -type ethClienter interface { +type ethereumClient interface { ethereum.ChainReader + ethereum.ChainStateReader + ethereum.ContractCaller + ethereum.GasEstimator + ethereum.GasPricer ethereum.LogFilterer ethereum.TransactionReader - ethereum.ContractCaller + ethereum.TransactionSender + + bind.DeployBackend +} + +// L1Config represents the configuration of the network used in L1 +type L1Config struct { + L1ChainID uint64 `json:"chainId"` + ZkEVMAddr common.Address `json:"polygonZkEVMAddress"` + MaticAddr common.Address `json:"maticTokenAddress"` + GlobalExitRootManagerAddr common.Address `json:"polygonZkEVMGlobalExitRootAddress"` +} + +type externalGasProviders struct { + MultiGasProvider bool + Providers []ethereum.GasPricer } // Client is a simple implementation of EtherMan. type Client struct { - EtherClient ethClienter - PoE *proofofefficiency.Proofofefficiency - GlobalExitRootManager *globalexitrootmanager.Globalexitrootmanager + EthClient ethereumClient + ZkEVM *polygonzkevm.Polygonzkevm + GlobalExitRootManager *polygonzkevmglobalexitroot.Polygonzkevmglobalexitroot Matic *matic.Matic SCAddresses []common.Address - auth *bind.TransactOpts + GasProviders externalGasProviders + + l1Cfg L1Config + auth map[common.Address]bind.TransactOpts // empty in case of read-only client } // NewClient creates a new etherman. -func NewClient(cfg Config, auth *bind.TransactOpts, PoEAddr common.Address, maticAddr common.Address, globalExitRootManAddr common.Address) (*Client, error) { +func NewClient(cfg Config, l1Config L1Config) (*Client, error) { // Connect to ethereum node ethClient, err := ethclient.Dial(cfg.URL) if err != nil { @@ -91,22 +148,116 @@ func NewClient(cfg Config, auth *bind.TransactOpts, PoEAddr common.Address, mati return nil, err } // Create smc clients - poe, err := proofofefficiency.NewProofofefficiency(PoEAddr, ethClient) + poe, err := polygonzkevm.NewPolygonzkevm(l1Config.ZkEVMAddr, ethClient) if err != nil { return nil, err } - globalExitRoot, err := globalexitrootmanager.NewGlobalexitrootmanager(globalExitRootManAddr, ethClient) + globalExitRoot, err := polygonzkevmglobalexitroot.NewPolygonzkevmglobalexitroot(l1Config.GlobalExitRootManagerAddr, ethClient) if err != nil { return nil, err } - matic, err := matic.NewMatic(maticAddr, ethClient) + matic, err := matic.NewMatic(l1Config.MaticAddr, ethClient) if err != nil { return nil, err } var scAddresses []common.Address - scAddresses = append(scAddresses, PoEAddr, globalExitRootManAddr) + scAddresses = append(scAddresses, l1Config.ZkEVMAddr, l1Config.GlobalExitRootManagerAddr) + + gProviders := []ethereum.GasPricer{ethClient} + if cfg.MultiGasProvider { + if cfg.Etherscan.ApiKey == "" { + log.Info("No ApiKey provided for etherscan. Ignoring provider...") + } else { + log.Info("ApiKey detected for etherscan") + gProviders = append(gProviders, etherscan.NewEtherscanService(cfg.Etherscan.ApiKey)) + } + gProviders = append(gProviders, ethgasstation.NewEthGasStationService()) + } + + return &Client{ + EthClient: ethClient, + ZkEVM: poe, + Matic: matic, + GlobalExitRootManager: globalExitRoot, + SCAddresses: scAddresses, + GasProviders: externalGasProviders{ + MultiGasProvider: cfg.MultiGasProvider, + Providers: gProviders, + }, + l1Cfg: l1Config, + auth: map[common.Address]bind.TransactOpts{}, + }, nil +} + +// VerifyGenBlockNumber verifies if the genesis Block Number is valid +func (etherMan *Client) VerifyGenBlockNumber(ctx context.Context, genBlockNumber uint64) (bool, error) { + log.Info("Verifying genesis blockNumber: ", genBlockNumber) + // Filter query + genBlock := new(big.Int).SetUint64(genBlockNumber) + query := ethereum.FilterQuery{ + FromBlock: genBlock, + ToBlock: genBlock, + Addresses: etherMan.SCAddresses, + Topics: [][]common.Hash{{updateZkEVMVersionSignatureHash}}, + } + logs, err := etherMan.EthClient.FilterLogs(ctx, query) + if err != nil { + return false, err + } + if len(logs) == 0 { + return false, fmt.Errorf("the specified genBlockNumber in config file does not contain any forkID event. Please use the proper blockNumber.") + } + zkevmVersion, err := etherMan.ZkEVM.ParseUpdateZkEVMVersion(logs[0]) + if err != nil { + log.Error("error parsing the forkID event") + return false, err + } + if zkevmVersion.NumBatch != 0 { + return false, fmt.Errorf("the specified genBlockNumber in config file does not contain the initial forkID event (BatchNum: %d). Please use the proper blockNumber.", zkevmVersion.NumBatch) + } + return true, nil +} - return &Client{EtherClient: ethClient, PoE: poe, Matic: matic, GlobalExitRootManager: globalExitRoot, SCAddresses: scAddresses, auth: auth}, nil +// GetForks returns fork information +func (etherMan *Client) GetForks(ctx context.Context, genBlockNumber uint64) ([]state.ForkIDInterval, error) { + log.Debug("Getting forkIDs from blockNumber: ", genBlockNumber) + // Filter query + query := ethereum.FilterQuery{ + FromBlock: new(big.Int).SetUint64(genBlockNumber), + Addresses: etherMan.SCAddresses, + Topics: [][]common.Hash{{updateZkEVMVersionSignatureHash}}, + } + logs, err := etherMan.EthClient.FilterLogs(ctx, query) + if err != nil { + return []state.ForkIDInterval{}, err + } + var forks []state.ForkIDInterval + for i, l := range logs { + zkevmVersion, err := etherMan.ZkEVM.ParseUpdateZkEVMVersion(l) + if err != nil { + return []state.ForkIDInterval{}, err + } + var fork state.ForkIDInterval + if i == 0 { + fork = state.ForkIDInterval{ + FromBatchNumber: zkevmVersion.NumBatch + 1, + ToBatchNumber: math.MaxUint64, + ForkId: zkevmVersion.ForkID, + Version: zkevmVersion.Version, + } + } else { + forks[len(forks)-1].ToBatchNumber = zkevmVersion.NumBatch + fork = state.ForkIDInterval{ + FromBatchNumber: zkevmVersion.NumBatch + 1, + ToBatchNumber: math.MaxUint64, + ForkId: zkevmVersion.ForkID, + Version: zkevmVersion.Version, + } + } + forks = append(forks, fork) + } + log.Debugf("Forks decoded: %+v", forks) + return forks, nil } // GetRollupInfoByBlockRange function retrieves the Rollup information that are included in all this ethereum blocks @@ -134,7 +285,7 @@ type Order struct { } func (etherMan *Client) readEvents(ctx context.Context, query ethereum.FilterQuery) ([]Block, map[common.Hash][]Order, error) { - logs, err := etherMan.EtherClient.FilterLogs(ctx, query) + logs, err := etherMan.EthClient.FilterLogs(ctx, query) if err != nil { return nil, nil, err } @@ -158,16 +309,16 @@ func (etherMan *Client) processEvent(ctx context.Context, vLog types.Log, blocks return etherMan.updateGlobalExitRootEvent(ctx, vLog, blocks, blocksOrder) case forcedBatchSignatureHash: return etherMan.forcedBatchEvent(ctx, vLog, blocks, blocksOrder) - case verifiedBatchSignatureHash: - return etherMan.verifyBatchEvent(ctx, vLog, blocks, blocksOrder) + case verifyBatchesTrustedAggregatorSignatureHash: + return etherMan.verifyBatchesTrustedAggregatorEvent(ctx, vLog, blocks, blocksOrder) + case verifyBatchesSignatureHash: + log.Warn("VerifyBatches event not implemented yet") + return nil case forceSequencedBatchesSignatureHash: return etherMan.forceSequencedBatchesEvent(ctx, vLog, blocks, blocksOrder) case setTrustedSequencerURLSignatureHash: log.Debug("SetTrustedSequencerURL event detected") return nil - case setForceBatchAllowedSignatureHash: - log.Debug("SetForceBatchAllowed event detected") - return nil case setTrustedSequencerSignatureHash: log.Debug("SetTrustedSequencer event detected") return nil @@ -186,11 +337,90 @@ func (etherMan *Client) processEvent(ctx context.Context, vLog types.Log, blocks case transferOwnershipSignatureHash: log.Debug("TransferOwnership event detected") return nil + case emergencyStateActivatedSignatureHash: + log.Debug("EmergencyStateActivated event detected") + return nil + case emergencyStateDeactivatedSignatureHash: + log.Debug("EmergencyStateDeactivated event detected") + return nil + case updateZkEVMVersionSignatureHash: + return etherMan.updateZkevmVersion(ctx, vLog, blocks, blocksOrder) + case consolidatePendingStateSignatureHash: + log.Debug("ConsolidatePendingState event detected") + return nil + case setTrustedAggregatorTimeoutSignatureHash: + log.Debug("SetTrustedAggregatorTimeout event detected") + return nil + case setTrustedAggregatorSignatureHash: + log.Debug("setTrustedAggregator event detected") + return nil + case setPendingStateTimeoutSignatureHash: + log.Debug("SetPendingStateTimeout event detected") + return nil + case setMultiplierBatchFeeSignatureHash: + log.Debug("SetMultiplierBatchFee event detected") + return nil + case setVerifyBatchTimeTargetSignatureHash: + log.Debug("SetVerifyBatchTimeTarget event detected") + return nil + case setForceBatchTimeoutSignatureHash: + log.Debug("SetForceBatchTimeout event detected") + return nil + case activateForceBatchesSignatureHash: + log.Debug("ActivateForceBatches event detected") + return nil + case transferAdminRoleSignatureHash: + log.Debug("TransferAdminRole event detected") + return nil + case acceptAdminRoleSignatureHash: + log.Debug("AcceptAdminRole event detected") + return nil + case proveNonDeterministicPendingStateSignatureHash: + log.Debug("ProveNonDeterministicPendingState event detected") + return nil + case overridePendingStateSignatureHash: + log.Debug("OverridePendingState event detected") + return nil } log.Warn("Event not registered: ", vLog) return nil } +func (etherMan *Client) updateZkevmVersion(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { + log.Debug("UpdateZkEVMVersion event detected") + zkevmVersion, err := etherMan.ZkEVM.ParseUpdateZkEVMVersion(vLog) + if err != nil { + log.Error("error parsing UpdateZkEVMVersion event. Error: ", err) + return err + } + fork := ForkID{ + BatchNumber: zkevmVersion.NumBatch, + ForkID: zkevmVersion.ForkID, + Version: zkevmVersion.Version, + } + if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) + } + t := time.Unix(int64(fullBlock.Time()), 0) + block := prepareBlock(vLog, t, fullBlock) + block.ForkIDs = append(block.ForkIDs, fork) + *blocks = append(*blocks, block) + } else if (*blocks)[len(*blocks)-1].BlockHash == vLog.BlockHash && (*blocks)[len(*blocks)-1].BlockNumber == vLog.BlockNumber { + (*blocks)[len(*blocks)-1].ForkIDs = append((*blocks)[len(*blocks)-1].ForkIDs, fork) + } else { + log.Error("Error processing updateZkevmVersion event. BlockHash:", vLog.BlockHash, ". BlockNumber: ", vLog.BlockNumber) + return fmt.Errorf("error processing updateZkevmVersion event") + } + or := Order{ + Name: ForkIDsOrder, + Pos: len((*blocks)[len(*blocks)-1].ForkIDs) - 1, + } + (*blocksOrder)[(*blocks)[len(*blocks)-1].BlockHash] = append((*blocksOrder)[(*blocks)[len(*blocks)-1].BlockHash], or) + return nil +} + func (etherMan *Client) updateGlobalExitRootEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { log.Debug("UpdateGlobalExitRoot event detected") globalExitRoot, err := etherMan.GlobalExitRootManager.ParseUpdateGlobalExitRoot(vLog) @@ -200,16 +430,16 @@ func (etherMan *Client) updateGlobalExitRootEvent(ctx context.Context, vLog type var gExitRoot GlobalExitRoot gExitRoot.MainnetExitRoot = common.BytesToHash(globalExitRoot.MainnetExitRoot[:]) gExitRoot.RollupExitRoot = common.BytesToHash(globalExitRoot.RollupExitRoot[:]) - gExitRoot.GlobalExitRootNum = globalExitRoot.GlobalExitRootNum gExitRoot.BlockNumber = vLog.BlockNumber gExitRoot.GlobalExitRoot = hash(globalExitRoot.MainnetExitRoot, globalExitRoot.RollupExitRoot) if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { - fullBlock, err := etherMan.EtherClient.BlockByHash(ctx, vLog.BlockHash) + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) if err != nil { return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) } - block := prepareBlock(vLog, time.Unix(int64(fullBlock.Time()), 0), fullBlock) + t := time.Unix(int64(fullBlock.Time()), 0) + block := prepareBlock(vLog, t, fullBlock) block.GlobalExitRoots = append(block.GlobalExitRoots, gExitRoot) *blocks = append(*blocks, block) } else if (*blocks)[len(*blocks)-1].BlockHash == vLog.BlockHash && (*blocks)[len(*blocks)-1].BlockNumber == vLog.BlockNumber { @@ -227,15 +457,26 @@ func (etherMan *Client) updateGlobalExitRootEvent(ctx context.Context, vLog type } // WaitTxToBeMined waits for an L1 tx to be mined. It will return error if the tx is reverted or timeout is exceeded -func (etherMan *Client) WaitTxToBeMined(hash common.Hash, timeout time.Duration) error { - return operations.WaitTxToBeMined(etherMan.EtherClient, hash, timeout) +func (etherMan *Client) WaitTxToBeMined(ctx context.Context, tx *types.Transaction, timeout time.Duration) (bool, error) { + err := operations.WaitTxToBeMined(ctx, etherMan.EthClient, tx, timeout) + if errors.Is(err, context.DeadlineExceeded) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil } // EstimateGasSequenceBatches estimates gas for sending batches -func (etherMan *Client) EstimateGasSequenceBatches(sequences []ethmanTypes.Sequence) (*types.Transaction, error) { - noSendOpts := *etherMan.auth - noSendOpts.NoSend = true - tx, err := etherMan.sequenceBatches(&noSendOpts, sequences) +func (etherMan *Client) EstimateGasSequenceBatches(sender common.Address, sequences []ethmanTypes.Sequence) (*types.Transaction, error) { + opts, err := etherMan.getAuthByAddress(sender) + if err == ErrNotFound { + return nil, ErrPrivateKeyNotFound + } + opts.NoSend = true + + tx, err := etherMan.sequenceBatches(opts, sequences) if err != nil { return nil, err } @@ -243,75 +484,111 @@ func (etherMan *Client) EstimateGasSequenceBatches(sequences []ethmanTypes.Seque return tx, nil } -// SequenceBatches send sequences of batches to the ethereum -func (etherMan *Client) SequenceBatches(sequences []ethmanTypes.Sequence, gasLimit uint64, gasPrice, nonce *big.Int) (*types.Transaction, error) { - sendSequencesOpts := *etherMan.auth - sendSequencesOpts.GasLimit = gasLimit - if gasPrice != nil { - sendSequencesOpts.GasPrice = gasPrice +// BuildSequenceBatchesTxData builds a []bytes to be sent to the PoE SC method SequenceBatches. +func (etherMan *Client) BuildSequenceBatchesTxData(sender common.Address, sequences []ethmanTypes.Sequence) (to *common.Address, data []byte, err error) { + opts, err := etherMan.getAuthByAddress(sender) + if err == ErrNotFound { + return nil, nil, fmt.Errorf("failed to build sequence batches, err: %w", ErrPrivateKeyNotFound) } - if nonce != nil { - sendSequencesOpts.Nonce = nonce + opts.NoSend = true + // force nonce, gas limit and gas price to avoid querying it from the chain + opts.Nonce = big.NewInt(1) + opts.GasLimit = uint64(1) + opts.GasPrice = big.NewInt(1) + + tx, err := etherMan.sequenceBatches(opts, sequences) + if err != nil { + return nil, nil, err } - return etherMan.sequenceBatches(&sendSequencesOpts, sequences) + + return tx.To(), tx.Data(), nil } -func (etherMan *Client) sequenceBatches(opts *bind.TransactOpts, sequences []ethmanTypes.Sequence) (*types.Transaction, error) { - var batches []proofofefficiency.ProofOfEfficiencyBatchData +func (etherMan *Client) sequenceBatches(opts bind.TransactOpts, sequences []ethmanTypes.Sequence) (*types.Transaction, error) { + var batches []polygonzkevm.PolygonZkEVMBatchData for _, seq := range sequences { - batchL2Data, err := state.EncodeTransactions(seq.Txs) - if err != nil { - return nil, fmt.Errorf("failed to encode transactions, err: %v", err) - } - batch := proofofefficiency.ProofOfEfficiencyBatchData{ - Transactions: batchL2Data, - GlobalExitRoot: seq.GlobalExitRoot, - Timestamp: uint64(seq.Timestamp), - ForceBatchesTimestamp: nil, + batch := polygonzkevm.PolygonZkEVMBatchData{ + Transactions: seq.BatchL2Data, + GlobalExitRoot: seq.GlobalExitRoot, + Timestamp: uint64(seq.Timestamp), + MinForcedTimestamp: uint64(seq.ForcedBatchTimestamp), } batches = append(batches, batch) } - return etherMan.PoE.SequenceBatches(opts, batches) -} -// EstimateGasForVerifyBatch estimates gas for verify batch smart contract call -func (etherMan *Client) EstimateGasForVerifyBatch(batchNumber uint64, resGetProof *pb.GetProofResponse) (uint64, error) { - verifyBatchOpts := *etherMan.auth - verifyBatchOpts.NoSend = true - tx, err := etherMan.verifyBatch(&verifyBatchOpts, batchNumber, resGetProof) + tx, err := etherMan.ZkEVM.SequenceBatches(&opts, batches, opts.From) if err != nil { - return 0, err + if parsedErr, ok := tryParseError(err); ok { + err = parsedErr + } } - return tx.Gas(), nil + + return tx, err } -// VerifyBatch send verifyBatch request to the ethereum -func (etherMan *Client) VerifyBatch(batchNumber uint64, resGetProof *pb.GetProofResponse, gasLimit uint64, gasPrice, nonce *big.Int) (*types.Transaction, error) { - verifyBatchOpts := *etherMan.auth - verifyBatchOpts.GasLimit = gasLimit - if gasPrice != nil { - verifyBatchOpts.GasPrice = gasPrice +// BuildTrustedVerifyBatchesTxData builds a []bytes to be sent to the PoE SC method TrustedVerifyBatches. +func (etherMan *Client) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, inputs *ethmanTypes.FinalProofInputs) (to *common.Address, data []byte, err error) { + opts, err := etherMan.generateRandomAuth() + if err != nil { + return nil, nil, fmt.Errorf("failed to build trusted verify batches, err: %w", err) } - if nonce != nil { - verifyBatchOpts.Nonce = nonce + opts.NoSend = true + // force nonce, gas limit and gas price to avoid querying it from the chain + opts.Nonce = big.NewInt(1) + opts.GasLimit = uint64(1) + opts.GasPrice = big.NewInt(1) + + var newLocalExitRoot [32]byte + copy(newLocalExitRoot[:], inputs.NewLocalExitRoot) + + var newStateRoot [32]byte + copy(newStateRoot[:], inputs.NewStateRoot) + + proof, err := encoding.DecodeBytes(&inputs.FinalProof.Proof) + if err != nil { + return nil, nil, fmt.Errorf("failed to decode proof, err: %w", err) + } + + const pendStateNum = 0 // TODO hardcoded for now until we implement the pending state feature + + tx, err := etherMan.ZkEVM.VerifyBatchesTrustedAggregator( + &opts, + pendStateNum, + lastVerifiedBatch, + newVerifiedBatch, + newLocalExitRoot, + newStateRoot, + proof, + ) + if err != nil { + if parsedErr, ok := tryParseError(err); ok { + err = parsedErr + } + return nil, nil, err } - return etherMan.verifyBatch(&verifyBatchOpts, batchNumber, resGetProof) + + return tx.To(), tx.Data(), nil } // GetSendSequenceFee get super/trusted sequencer fee -func (etherMan *Client) GetSendSequenceFee() (*big.Int, error) { - return etherMan.PoE.TRUSTEDSEQUENCERFEE(&bind.CallOpts{Pending: false}) +func (etherMan *Client) GetSendSequenceFee(numBatches uint64) (*big.Int, error) { + f, err := etherMan.ZkEVM.BatchFee(&bind.CallOpts{Pending: false}) + if err != nil { + return nil, err + } + fee := new(big.Int).Mul(f, new(big.Int).SetUint64(numBatches)) + return fee, nil } // TrustedSequencer gets trusted sequencer address func (etherMan *Client) TrustedSequencer() (common.Address, error) { - return etherMan.PoE.TrustedSequencer(&bind.CallOpts{Pending: false}) + return etherMan.ZkEVM.TrustedSequencer(&bind.CallOpts{Pending: false}) } func (etherMan *Client) forcedBatchEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { log.Debug("ForceBatch event detected") - fb, err := etherMan.PoE.ParseForceBatch(vLog) + fb, err := etherMan.ZkEVM.ParseForceBatch(vLog) if err != nil { return err } @@ -320,30 +597,48 @@ func (etherMan *Client) forcedBatchEvent(ctx context.Context, vLog types.Log, bl forcedBatch.ForcedBatchNumber = fb.ForceBatchNum forcedBatch.GlobalExitRoot = fb.LastGlobalExitRoot // Read the tx for this batch. - tx, isPending, err := etherMan.EtherClient.TransactionByHash(ctx, vLog.TxHash) + tx, isPending, err := etherMan.EthClient.TransactionByHash(ctx, vLog.TxHash) if err != nil { return err } else if isPending { return fmt.Errorf("error: tx is still pending. TxHash: %s", tx.Hash().String()) } - msg, err := tx.AsMessage(types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) + msg, err := core.TransactionToMessage(tx, types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) if err != nil { - log.Error(err) return err } - if fb.Sequencer == msg.From() { - forcedBatch.RawTxsData = tx.Data() + if fb.Sequencer == msg.From { + txData := tx.Data() + // Extract coded txs. + // Load contract ABI + abi, err := abi.JSON(strings.NewReader(polygonzkevm.PolygonzkevmABI)) + if err != nil { + return err + } + + // Recover Method from signature and ABI + method, err := abi.MethodById(txData[:4]) + if err != nil { + return err + } + + // Unpack method inputs + data, err := method.Inputs.Unpack(txData[4:]) + if err != nil { + return err + } + bytedata := data[0].([]byte) + forcedBatch.RawTxsData = bytedata } else { forcedBatch.RawTxsData = fb.Transactions } forcedBatch.Sequencer = fb.Sequencer - fullBlock, err := etherMan.EtherClient.BlockByHash(ctx, vLog.BlockHash) + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) if err != nil { return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) } t := time.Unix(int64(fullBlock.Time()), 0) forcedBatch.ForcedAt = t - if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { block := prepareBlock(vLog, t, fullBlock) block.ForcedBatches = append(block.ForcedBatches, forcedBatch) @@ -364,29 +659,28 @@ func (etherMan *Client) forcedBatchEvent(ctx context.Context, vLog types.Log, bl func (etherMan *Client) sequencedBatchesEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { log.Debug("SequenceBatches event detected") - sb, err := etherMan.PoE.ParseSequenceBatches(vLog) + sb, err := etherMan.ZkEVM.ParseSequenceBatches(vLog) if err != nil { return err } // Read the tx for this event. - tx, isPending, err := etherMan.EtherClient.TransactionByHash(ctx, vLog.TxHash) + tx, isPending, err := etherMan.EthClient.TransactionByHash(ctx, vLog.TxHash) if err != nil { return err } else if isPending { return fmt.Errorf("error tx is still pending. TxHash: %s", tx.Hash().String()) } - msg, err := tx.AsMessage(types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) + msg, err := core.TransactionToMessage(tx, types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) if err != nil { - log.Error(err) return err } - sequences, err := decodeSequences(tx.Data(), sb.NumBatch, msg.From(), vLog.TxHash) + sequences, err := decodeSequences(tx.Data(), sb.NumBatch, msg.From, vLog.TxHash, msg.Nonce) if err != nil { return fmt.Errorf("error decoding the sequences: %v", err) } if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { - fullBlock, err := etherMan.EtherClient.BlockByHash(ctx, vLog.BlockHash) + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) if err != nil { return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) } @@ -407,10 +701,10 @@ func (etherMan *Client) sequencedBatchesEvent(ctx context.Context, vLog types.Lo return nil } -func decodeSequences(txData []byte, lastBatchNumber uint64, sequencer common.Address, txHash common.Hash) ([]SequencedBatch, error) { +func decodeSequences(txData []byte, lastBatchNumber uint64, sequencer common.Address, txHash common.Hash, nonce uint64) ([]SequencedBatch, error) { // Extract coded txs. // Load contract ABI - abi, err := abi.JSON(strings.NewReader(proofofefficiency.ProofofefficiencyABI)) + abi, err := abi.JSON(strings.NewReader(polygonzkevm.PolygonzkevmABI)) if err != nil { return nil, err } @@ -426,7 +720,7 @@ func decodeSequences(txData []byte, lastBatchNumber uint64, sequencer common.Add if err != nil { return nil, err } - var sequences []proofofefficiency.ProofOfEfficiencyBatchData + var sequences []polygonzkevm.PolygonZkEVMBatchData bytedata, err := json.Marshal(data[0]) if err != nil { return nil, err @@ -435,51 +729,52 @@ func decodeSequences(txData []byte, lastBatchNumber uint64, sequencer common.Add if err != nil { return nil, err } - + coinbase := (data[1]).(common.Address) sequencedBatches := make([]SequencedBatch, len(sequences)) - for i := len(sequences) - 1; i >= 0; i-- { - lastBatchNumber -= uint64(len(sequences[i].ForceBatchesTimestamp)) + for i, seq := range sequences { + bn := lastBatchNumber - uint64(len(sequences)-(i+1)) sequencedBatches[i] = SequencedBatch{ - BatchNumber: lastBatchNumber, - Coinbase: sequencer, - TxHash: txHash, - ProofOfEfficiencyBatchData: sequences[i], + BatchNumber: bn, + SequencerAddr: sequencer, + TxHash: txHash, + Nonce: nonce, + Coinbase: coinbase, + PolygonZkEVMBatchData: seq, } - lastBatchNumber-- } return sequencedBatches, nil } -func (etherMan *Client) verifyBatchEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { - log.Debug("VerifyBatch event detected") - vb, err := etherMan.PoE.ParseVerifyBatch(vLog) +func (etherMan *Client) verifyBatchesTrustedAggregatorEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { + log.Debug("TrustedVerifyBatches event detected") + vb, err := etherMan.ZkEVM.ParseVerifyBatchesTrustedAggregator(vLog) if err != nil { return err } - var verifyBatch VerifiedBatch - verifyBatch.BlockNumber = vLog.BlockNumber - verifyBatch.BatchNumber = vb.NumBatch - verifyBatch.TxHash = vLog.TxHash - verifyBatch.Aggregator = vb.Aggregator + var trustedVerifyBatch VerifiedBatch + trustedVerifyBatch.BlockNumber = vLog.BlockNumber + trustedVerifyBatch.BatchNumber = vb.NumBatch + trustedVerifyBatch.TxHash = vLog.TxHash + trustedVerifyBatch.StateRoot = vb.StateRoot + trustedVerifyBatch.Aggregator = vb.Aggregator if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { - fullBlock, err := etherMan.EtherClient.BlockByHash(ctx, vLog.BlockHash) + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) if err != nil { return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) } block := prepareBlock(vLog, time.Unix(int64(fullBlock.Time()), 0), fullBlock) - *blocks = append(*blocks, block) - block.VerifiedBatches = append(block.VerifiedBatches, verifyBatch) + block.VerifiedBatches = append(block.VerifiedBatches, trustedVerifyBatch) *blocks = append(*blocks, block) } else if (*blocks)[len(*blocks)-1].BlockHash == vLog.BlockHash && (*blocks)[len(*blocks)-1].BlockNumber == vLog.BlockNumber { - (*blocks)[len(*blocks)-1].VerifiedBatches = append((*blocks)[len(*blocks)-1].VerifiedBatches, verifyBatch) + (*blocks)[len(*blocks)-1].VerifiedBatches = append((*blocks)[len(*blocks)-1].VerifiedBatches, trustedVerifyBatch) } else { - log.Error("Error processing VerifyBatch event. BlockHash:", vLog.BlockHash, ". BlockNumber: ", vLog.BlockNumber) - return fmt.Errorf("error processing VerifyBatch event") + log.Error("Error processing trustedVerifyBatch event. BlockHash:", vLog.BlockHash, ". BlockNumber: ", vLog.BlockNumber) + return fmt.Errorf("error processing trustedVerifyBatch event") } or := Order{ - Name: VerifyBatchOrder, + Name: TrustedVerifyBatchOrder, Pos: len((*blocks)[len(*blocks)-1].VerifiedBatches) - 1, } (*blocksOrder)[(*blocks)[len(*blocks)-1].BlockHash] = append((*blocksOrder)[(*blocks)[len(*blocks)-1].BlockHash], or) @@ -488,40 +783,32 @@ func (etherMan *Client) verifyBatchEvent(ctx context.Context, vLog types.Log, bl func (etherMan *Client) forceSequencedBatchesEvent(ctx context.Context, vLog types.Log, blocks *[]Block, blocksOrder *map[common.Hash][]Order) error { log.Debug("SequenceForceBatches event detect") - fsb, err := etherMan.PoE.ParseSequenceForceBatches(vLog) + fsb, err := etherMan.ZkEVM.ParseSequenceForceBatches(vLog) if err != nil { return err } - var sequencedForceBatch SequencedForceBatch - sequencedForceBatch.LastBatchSequenced = fsb.NumBatch - if err != nil { - return err - } // Read the tx for this batch. - tx, isPending, err := etherMan.EtherClient.TransactionByHash(ctx, vLog.TxHash) + tx, isPending, err := etherMan.EthClient.TransactionByHash(ctx, vLog.TxHash) if err != nil { return err } else if isPending { return fmt.Errorf("error: tx is still pending. TxHash: %s", tx.Hash().String()) } - msg, err := tx.AsMessage(types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) + msg, err := core.TransactionToMessage(tx, types.NewLondonSigner(tx.ChainId()), big.NewInt(0)) if err != nil { - log.Error(err) return err } - sequencedForceBatch.Coinbase = msg.From() - sequencedForceBatch.ForceBatchNumber, err = decodeForceBatchNumber(tx.Data()) - sequencedForceBatch.TxHash = vLog.TxHash + fullBlock, err := etherMan.EthClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) + } + sequencedForceBatch, err := decodeSequencedForceBatches(tx.Data(), fsb.NumBatch, msg.From, vLog.TxHash, fullBlock, msg.Nonce) if err != nil { return err } if len(*blocks) == 0 || ((*blocks)[len(*blocks)-1].BlockHash != vLog.BlockHash || (*blocks)[len(*blocks)-1].BlockNumber != vLog.BlockNumber) { - fullBlock, err := etherMan.EtherClient.BlockByHash(ctx, vLog.BlockHash) - if err != nil { - return fmt.Errorf("error getting hashParent. BlockNumber: %d. Error: %w", vLog.BlockNumber, err) - } block := prepareBlock(vLog, time.Unix(int64(fullBlock.Time()), 0), fullBlock) block.SequencedForceBatches = append(block.SequencedForceBatches, sequencedForceBatch) *blocks = append(*blocks, block) @@ -540,27 +827,49 @@ func (etherMan *Client) forceSequencedBatchesEvent(ctx context.Context, vLog typ return nil } -func decodeForceBatchNumber(txData []byte) (uint64, error) { +func decodeSequencedForceBatches(txData []byte, lastBatchNumber uint64, sequencer common.Address, txHash common.Hash, block *types.Block, nonce uint64) ([]SequencedForceBatch, error) { // Extract coded txs. // Load contract ABI - abi, err := abi.JSON(strings.NewReader(proofofefficiency.ProofofefficiencyABI)) + abi, err := abi.JSON(strings.NewReader(polygonzkevm.PolygonzkevmABI)) if err != nil { - return 0, err + return nil, err } // Recover Method from signature and ABI method, err := abi.MethodById(txData[:4]) if err != nil { - return 0, err + return nil, err } // Unpack method inputs data, err := method.Inputs.Unpack(txData[4:]) if err != nil { - return 0, err + return nil, err } - return data[0].(uint64), nil + var forceBatches []polygonzkevm.PolygonZkEVMForcedBatchData + bytedata, err := json.Marshal(data[0]) + if err != nil { + return nil, err + } + err = json.Unmarshal(bytedata, &forceBatches) + if err != nil { + return nil, err + } + + sequencedForcedBatches := make([]SequencedForceBatch, len(forceBatches)) + for i, force := range forceBatches { + bn := lastBatchNumber - uint64(len(forceBatches)-(i+1)) + sequencedForcedBatches[i] = SequencedForceBatch{ + BatchNumber: bn, + Coinbase: sequencer, + TxHash: txHash, + Timestamp: time.Unix(int64(block.Time()), 0), + Nonce: nonce, + PolygonZkEVMForcedBatchData: force, + } + } + return sequencedForcedBatches, nil } func prepareBlock(vLog types.Log, t time.Time, fullBlock *types.Block) Block { @@ -585,12 +894,12 @@ func hash(data ...[32]byte) [32]byte { // HeaderByNumber returns a block header from the current canonical chain. If number is // nil, the latest known header is returned. func (etherMan *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { - return etherMan.EtherClient.HeaderByNumber(ctx, number) + return etherMan.EthClient.HeaderByNumber(ctx, number) } // EthBlockByNumber function retrieves the ethereum block information by ethereum block number. func (etherMan *Client) EthBlockByNumber(ctx context.Context, blockNumber uint64) (*types.Block, error) { - block, err := etherMan.EtherClient.BlockByNumber(ctx, new(big.Int).SetUint64(blockNumber)) + block, err := etherMan.EthClient.BlockByNumber(ctx, new(big.Int).SetUint64(blockNumber)) if err != nil { if errors.Is(err, ethereum.NotFound) || err.Error() == "block does not exist in blockchain" { return nil, ErrNotFound @@ -602,17 +911,17 @@ func (etherMan *Client) EthBlockByNumber(ctx context.Context, blockNumber uint64 // GetLastBatchTimestamp function allows to retrieve the lastTimestamp value in the smc func (etherMan *Client) GetLastBatchTimestamp() (uint64, error) { - return etherMan.PoE.LastTimestamp(&bind.CallOpts{Pending: false}) + return etherMan.ZkEVM.LastTimestamp(&bind.CallOpts{Pending: false}) } // GetLatestBatchNumber function allows to retrieve the latest proposed batch in the smc func (etherMan *Client) GetLatestBatchNumber() (uint64, error) { - return etherMan.PoE.LastBatchSequenced(&bind.CallOpts{Pending: false}) + return etherMan.ZkEVM.LastBatchSequenced(&bind.CallOpts{Pending: false}) } // GetLatestBlockNumber gets the latest block number from the ethereum func (etherMan *Client) GetLatestBlockNumber(ctx context.Context) (uint64, error) { - header, err := etherMan.EtherClient.HeaderByNumber(ctx, nil) + header, err := etherMan.EthClient.HeaderByNumber(ctx, nil) if err != nil || header == nil { return 0, err } @@ -621,7 +930,7 @@ func (etherMan *Client) GetLatestBlockNumber(ctx context.Context) (uint64, error // GetLatestBlockTimestamp gets the latest block timestamp from the ethereum func (etherMan *Client) GetLatestBlockTimestamp(ctx context.Context) (uint64, error) { - header, err := etherMan.EtherClient.HeaderByNumber(ctx, nil) + header, err := etherMan.EthClient.HeaderByNumber(ctx, nil) if err != nil || header == nil { return 0, err } @@ -630,81 +939,227 @@ func (etherMan *Client) GetLatestBlockTimestamp(ctx context.Context) (uint64, er // GetLatestVerifiedBatchNum gets latest verified batch from ethereum func (etherMan *Client) GetLatestVerifiedBatchNum() (uint64, error) { - return etherMan.PoE.LastVerifiedBatch(&bind.CallOpts{Pending: false}) + return etherMan.ZkEVM.LastVerifiedBatch(&bind.CallOpts{Pending: false}) } // GetTx function get ethereum tx func (etherMan *Client) GetTx(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { - return etherMan.EtherClient.TransactionByHash(ctx, txHash) + return etherMan.EthClient.TransactionByHash(ctx, txHash) } // GetTxReceipt function gets ethereum tx receipt func (etherMan *Client) GetTxReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { - return etherMan.EtherClient.TransactionReceipt(ctx, txHash) + return etherMan.EthClient.TransactionReceipt(ctx, txHash) } // ApproveMatic function allow to approve tokens in matic smc -func (etherMan *Client) ApproveMatic(maticAmount *big.Int, to common.Address) (*types.Transaction, error) { - tx, err := etherMan.Matic.Approve(etherMan.auth, etherMan.SCAddresses[0], maticAmount) +func (etherMan *Client) ApproveMatic(ctx context.Context, account common.Address, maticAmount *big.Int, to common.Address) (*types.Transaction, error) { + opts, err := etherMan.getAuthByAddress(account) + if err == ErrNotFound { + return nil, errors.New("can't find account private key to sign tx") + } + if etherMan.GasProviders.MultiGasProvider { + opts.GasPrice = etherMan.GetL1GasPrice(ctx) + } + tx, err := etherMan.Matic.Approve(&opts, etherMan.l1Cfg.ZkEVMAddr, maticAmount) if err != nil { + if parsedErr, ok := tryParseError(err); ok { + err = parsedErr + } return nil, fmt.Errorf("error approving balance to send the batch. Error: %w", err) } + return tx, nil } // GetTrustedSequencerURL Gets the trusted sequencer url from rollup smc func (etherMan *Client) GetTrustedSequencerURL() (string, error) { - return etherMan.PoE.TrustedSequencerURL(&bind.CallOpts{Pending: false}) -} - -// GetPublicAddress returns eth client public address -func (etherMan *Client) GetPublicAddress() common.Address { - return etherMan.auth.From + return etherMan.ZkEVM.TrustedSequencerURL(&bind.CallOpts{Pending: false}) } // GetL2ChainID returns L2 Chain ID func (etherMan *Client) GetL2ChainID() (uint64, error) { - return etherMan.PoE.ChainID(&bind.CallOpts{Pending: false}) + return etherMan.ZkEVM.ChainID(&bind.CallOpts{Pending: false}) +} + +// GetL2ForkID returns current L2 Fork ID +func (etherMan *Client) GetL2ForkID() (uint64, error) { + // TODO: implement this + return 1, nil +} + +// GetL2ForkIDIntervals return L2 Fork ID intervals +func (etherMan *Client) GetL2ForkIDIntervals() ([]state.ForkIDInterval, error) { + // TODO: implement this + return []state.ForkIDInterval{{FromBatchNumber: 0, ToBatchNumber: math.MaxUint64, ForkId: 1}}, nil +} + +// GetL1GasPrice gets the l1 gas price +func (etherMan *Client) GetL1GasPrice(ctx context.Context) *big.Int { + // Get gasPrice from providers + gasPrice := big.NewInt(0) + for i, prov := range etherMan.GasProviders.Providers { + gp, err := prov.SuggestGasPrice(ctx) + if err != nil { + log.Warnf("error getting gas price from provider %d. Error: %s", i+1, err.Error()) + } else if gasPrice.Cmp(gp) == -1 { // gasPrice < gp + gasPrice = gp + } + } + log.Debug("gasPrice chose: ", gasPrice) + return gasPrice +} + +// SendTx sends a tx to L1 +func (etherMan *Client) SendTx(ctx context.Context, tx *types.Transaction) error { + return etherMan.EthClient.SendTransaction(ctx, tx) +} + +// CurrentNonce returns the current nonce for the provided account +func (etherMan *Client) CurrentNonce(ctx context.Context, account common.Address) (uint64, error) { + return etherMan.EthClient.NonceAt(ctx, account, nil) +} + +// SuggestedGasPrice returns the suggest nonce for the network at the moment +func (etherMan *Client) SuggestedGasPrice(ctx context.Context) (*big.Int, error) { + suggestedGasPrice := etherMan.GetL1GasPrice(ctx) + if suggestedGasPrice.Cmp(big.NewInt(0)) == 0 { + return nil, errors.New("failed to get the suggested gas price") + } + return suggestedGasPrice, nil +} + +// EstimateGas returns the estimated gas for the tx +func (etherMan *Client) EstimateGas(ctx context.Context, from common.Address, to *common.Address, value *big.Int, data []byte) (uint64, error) { + return etherMan.EthClient.EstimateGas(ctx, ethereum.CallMsg{ + From: from, + To: to, + Value: value, + Data: data, + }) +} + +// CheckTxWasMined check if a tx was already mined +func (etherMan *Client) CheckTxWasMined(ctx context.Context, txHash common.Hash) (bool, *types.Receipt, error) { + receipt, err := etherMan.EthClient.TransactionReceipt(ctx, txHash) + if errors.Is(err, ethereum.NotFound) { + return false, nil, nil + } else if err != nil { + return false, nil, err + } + + return true, receipt, nil } -// VerifyBatch function allows the aggregator send the proof for a batch and consolidate it -func (etherMan *Client) verifyBatch(opts *bind.TransactOpts, batchNumber uint64, resGetProof *pb.GetProofResponse) (*types.Transaction, error) { - publicInputs := resGetProof.Public.PublicInputs - newLocalExitRoot, err := stringToFixedByteArray(publicInputs.NewLocalExitRoot) +// SignTx tries to sign a transaction accordingly to the provided sender +func (etherMan *Client) SignTx(ctx context.Context, sender common.Address, tx *types.Transaction) (*types.Transaction, error) { + auth, err := etherMan.getAuthByAddress(sender) + if err == ErrNotFound { + return nil, ErrPrivateKeyNotFound + } + signedTx, err := auth.Signer(auth.From, tx) if err != nil { return nil, err } - newStateRoot, err := stringToFixedByteArray(publicInputs.NewStateRoot) + return signedTx, nil +} + +// GetRevertMessage tries to get a revert message of a transaction +func (etherMan *Client) GetRevertMessage(ctx context.Context, tx *types.Transaction) (string, error) { + if tx == nil { + return "", nil + } + + receipt, err := etherMan.GetTxReceipt(ctx, tx.Hash()) if err != nil { - return nil, err + return "", err } - proofA, err := strSliceToBigIntArray(resGetProof.Proof.ProofA) + if receipt.Status == types.ReceiptStatusFailed { + revertMessage, err := operations.RevertReason(ctx, etherMan.EthClient, tx, receipt.BlockNumber) + if err != nil { + return "", err + } + return revertMessage, nil + } + return "", nil +} + +// AddOrReplaceAuth adds an authorization or replace an existent one to the same account +func (etherMan *Client) AddOrReplaceAuth(auth bind.TransactOpts) error { + log.Infof("added or replaced authorization for address: %v", auth.From.String()) + etherMan.auth[auth.From] = auth + return nil +} + +// LoadAuthFromKeyStore loads an authorization from a key store file +func (etherMan *Client) LoadAuthFromKeyStore(path, password string) (*bind.TransactOpts, error) { + auth, err := newAuthFromKeystore(path, password, etherMan.l1Cfg.L1ChainID) if err != nil { return nil, err } - proofB, err := proofSlcToIntArray(resGetProof.Proof.ProofB) + log.Infof("loaded authorization for address: %v", auth.From.String()) + etherMan.auth[auth.From] = auth + return &auth, nil +} + +// newKeyFromKeystore creates an instance of a keystore key from a keystore file +func newKeyFromKeystore(path, password string) (*keystore.Key, error) { + if path == "" && password == "" { + return nil, nil + } + keystoreEncrypted, err := os.ReadFile(filepath.Clean(path)) if err != nil { return nil, err } - proofC, err := strSliceToBigIntArray(resGetProof.Proof.ProofC) + log.Infof("decrypting key from: %v", path) + key, err := keystore.DecryptKey(keystoreEncrypted, password) if err != nil { return nil, err } + return key, nil +} - tx, err := etherMan.PoE.VerifyBatch( - opts, - newLocalExitRoot, - newStateRoot, - batchNumber, - proofA, - proofB, - proofC, - ) +// newAuthFromKeystore an authorization instance from a keystore file +func newAuthFromKeystore(path, password string, chainID uint64) (bind.TransactOpts, error) { + log.Infof("reading key from: %v", path) + key, err := newKeyFromKeystore(path, password) + if err != nil { + return bind.TransactOpts{}, err + } + if key == nil { + return bind.TransactOpts{}, nil + } + auth, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, new(big.Int).SetUint64(chainID)) + if err != nil { + return bind.TransactOpts{}, err + } + return *auth, nil +} + +// getAuthByAddress tries to get an authorization from the authorizations map +func (etherMan *Client) getAuthByAddress(addr common.Address) (bind.TransactOpts, error) { + auth, found := etherMan.auth[addr] + if !found { + return bind.TransactOpts{}, ErrNotFound + } + return auth, nil +} +// generateRandomAuth generates an authorization instance from a +// randomly generated private key to be used to estimate gas for PoE +// operations NOT restricted to the Trusted Sequencer +func (etherMan *Client) generateRandomAuth() (bind.TransactOpts, error) { + privateKey, err := crypto.GenerateKey() if err != nil { - return nil, err + return bind.TransactOpts{}, errors.New("failed to generate a private key to estimate L1 txs") } - return tx, nil + chainID := big.NewInt(0).SetUint64(etherMan.l1Cfg.L1ChainID) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + if err != nil { + return bind.TransactOpts{}, errors.New("failed to generate a fake authorization to estimate L1 txs") + } + + return *auth, nil } diff --git a/etherman/etherman_test.go b/etherman/etherman_test.go index 347d9a1b9f..8985bb2b1e 100644 --- a/etherman/etherman_test.go +++ b/etherman/etherman_test.go @@ -3,14 +3,18 @@ package etherman import ( "context" "encoding/hex" + "fmt" + "math" "math/big" "testing" "time" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/bridge" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmbridge" ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" @@ -23,17 +27,17 @@ import ( func init() { log.Init(log.Config{ Level: "debug", - Outputs: []string{"stdout"}, + Outputs: []string{"stderr"}, }) } -//This function prepare the blockchain, the wallet with funds and deploy the smc -func newTestingEnv() (ethman *Client, ethBackend *backends.SimulatedBackend, maticAddr common.Address, br *bridge.Bridge) { +// This function prepare the blockchain, the wallet with funds and deploy the smc +func newTestingEnv() (ethman *Client, ethBackend *backends.SimulatedBackend, auth *bind.TransactOpts, maticAddr common.Address, br *polygonzkevmbridge.Polygonzkevmbridge) { privateKey, err := crypto.GenerateKey() if err != nil { log.Fatal(err) } - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) + auth, err = bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) if err != nil { log.Fatal(err) } @@ -41,210 +45,213 @@ func newTestingEnv() (ethman *Client, ethBackend *backends.SimulatedBackend, mat if err != nil { log.Fatal(err) } - return ethman, ethBackend, maticAddr, br + err = ethman.AddOrReplaceAuth(*auth) + if err != nil { + log.Fatal(err) + } + return ethman, ethBackend, auth, maticAddr, br } func TestGEREvent(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, br := newTestingEnv() + etherman, ethBackend, auth, _, br := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) amount := big.NewInt(1000000000000000) - a := etherman.auth - a.Value = amount - _, err = br.Bridge(a, common.Address{}, 1, etherman.auth.From, amount, []byte{}) + auth.Value = amount + _, err = br.BridgeAsset(auth, 1, auth.From, amount, common.Address{}, true, []byte{}) require.NoError(t, err) // Mine the tx in a block ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) finalBlockNumber := finalBlock.NumberU64() blocks, _, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - - assert.Equal(t, uint64(2), blocks[0].GlobalExitRoots[0].BlockNumber) - assert.Equal(t, big.NewInt(1), blocks[0].GlobalExitRoots[0].GlobalExitRootNum) - assert.NotEqual(t, common.Hash{}, blocks[0].GlobalExitRoots[0].MainnetExitRoot) - assert.Equal(t, common.Hash{}, blocks[0].GlobalExitRoots[0].RollupExitRoot) + t.Log("Blocks: ", blocks) + assert.Equal(t, uint64(2), blocks[1].GlobalExitRoots[0].BlockNumber) + assert.NotEqual(t, common.Hash{}, blocks[1].GlobalExitRoots[0].MainnetExitRoot) + assert.Equal(t, common.Hash{}, blocks[1].GlobalExitRoots[0].RollupExitRoot) } func TestForcedBatchEvent(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, _ := newTestingEnv() + etherman, ethBackend, auth, _, _ := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) - amount, err := etherman.PoE.CalculateForceProverFee(&bind.CallOpts{Pending: false}) + amount, err := etherman.ZkEVM.GetForcedBatchFee(&bind.CallOpts{Pending: false}) require.NoError(t, err) rawTxs := "f84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c" data, err := hex.DecodeString(rawTxs) require.NoError(t, err) - _, err = etherman.PoE.ForceBatch(etherman.auth, data, amount) + _, err = etherman.ZkEVM.ForceBatch(auth, data, amount) require.NoError(t, err) // Mine the tx in a block ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) finalBlockNumber := finalBlock.NumberU64() blocks, _, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - assert.Equal(t, uint64(2), blocks[0].BlockNumber) - assert.Equal(t, uint64(2), blocks[0].ForcedBatches[0].BlockNumber) - assert.NotEqual(t, common.Hash{}, blocks[0].ForcedBatches[0].GlobalExitRoot) - assert.NotEqual(t, time.Time{}, blocks[0].ForcedBatches[0].ForcedAt) - assert.Equal(t, uint64(1), blocks[0].ForcedBatches[0].ForcedBatchNumber) - dataFromSmc := "eaeb077b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000008cf84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c0000000000000000000000000000000000000000" - assert.Equal(t, dataFromSmc, hex.EncodeToString(blocks[0].ForcedBatches[0].RawTxsData)) - assert.Equal(t, etherman.auth.From, blocks[0].ForcedBatches[0].Sequencer) + t.Log("Blocks: ", blocks) + assert.Equal(t, uint64(2), blocks[1].BlockNumber) + assert.Equal(t, uint64(2), blocks[1].ForcedBatches[0].BlockNumber) + assert.NotEqual(t, common.Hash{}, blocks[1].ForcedBatches[0].GlobalExitRoot) + assert.NotEqual(t, time.Time{}, blocks[1].ForcedBatches[0].ForcedAt) + assert.Equal(t, uint64(1), blocks[1].ForcedBatches[0].ForcedBatchNumber) + assert.Equal(t, rawTxs, hex.EncodeToString(blocks[1].ForcedBatches[0].RawTxsData)) + assert.Equal(t, auth.From, blocks[1].ForcedBatches[0].Sequencer) } func TestSequencedBatchesEvent(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, br := newTestingEnv() + etherman, ethBackend, auth, _, br := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) // Make a bridge tx - a := etherman.auth - a.Value = big.NewInt(1000000000000000) - _, err = br.Bridge(a, common.Address{}, 1, a.From, a.Value, []byte{}) + auth.Value = big.NewInt(1000000000000000) + _, err = br.BridgeAsset(auth, 1, auth.From, auth.Value, common.Address{}, true, []byte{}) require.NoError(t, err) ethBackend.Commit() - a.Value = big.NewInt(0) + auth.Value = big.NewInt(0) // Get the last ger ger, err := etherman.GlobalExitRootManager.GetLastGlobalExitRoot(nil) require.NoError(t, err) - amount, err := etherman.PoE.CalculateForceProverFee(&bind.CallOpts{Pending: false}) + amount, err := etherman.ZkEVM.GetForcedBatchFee(&bind.CallOpts{Pending: false}) require.NoError(t, err) rawTxs := "f84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c" data, err := hex.DecodeString(rawTxs) require.NoError(t, err) - _, err = etherman.PoE.ForceBatch(etherman.auth, data, amount) + _, err = etherman.ZkEVM.ForceBatch(auth, data, amount) require.NoError(t, err) require.NoError(t, err) ethBackend.Commit() - currentBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) - require.NoError(t, err) - - var sequences []proofofefficiency.ProofOfEfficiencyBatchData - sequences = append(sequences, proofofefficiency.ProofOfEfficiencyBatchData{ - GlobalExitRoot: ger, - Timestamp: currentBlock.Time() - 1, - ForceBatchesTimestamp: []uint64{30}, - Transactions: common.Hex2Bytes(rawTxs), + // Now read the event + currentBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + currentBlockNumber := currentBlock.NumberU64() + blocks, _, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), ¤tBlockNumber) + require.NoError(t, err) + t.Log("Blocks: ", blocks) + var sequences []polygonzkevm.PolygonZkEVMBatchData + sequences = append(sequences, polygonzkevm.PolygonZkEVMBatchData{ + GlobalExitRoot: ger, + Timestamp: currentBlock.Time(), + MinForcedTimestamp: uint64(blocks[2].ForcedBatches[0].ForcedAt.Unix()), + Transactions: common.Hex2Bytes(rawTxs), }) - sequences = append(sequences, proofofefficiency.ProofOfEfficiencyBatchData{ - GlobalExitRoot: ger, - Timestamp: currentBlock.Time() + 1, - ForceBatchesTimestamp: []uint64{}, - Transactions: common.Hex2Bytes(rawTxs), + sequences = append(sequences, polygonzkevm.PolygonZkEVMBatchData{ + GlobalExitRoot: ger, + Timestamp: currentBlock.Time() + 1, + MinForcedTimestamp: 0, + Transactions: common.Hex2Bytes(rawTxs), }) - _, err = etherman.PoE.SequenceBatches(etherman.auth, sequences) + _, err = etherman.ZkEVM.SequenceBatches(auth, sequences, auth.From) require.NoError(t, err) // Mine the tx in a block ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) finalBlockNumber := finalBlock.NumberU64() blocks, order, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - assert.Equal(t, 3, len(blocks)) - assert.Equal(t, 1, len(blocks[2].SequencedBatches)) - assert.Equal(t, common.Hex2Bytes(rawTxs), blocks[2].SequencedBatches[0][1].Transactions) - assert.Equal(t, currentBlock.Time()-1, blocks[2].SequencedBatches[0][0].Timestamp) - assert.Equal(t, ger, blocks[2].SequencedBatches[0][0].GlobalExitRoot) - assert.Equal(t, []uint64{currentBlock.Time()}, blocks[2].SequencedBatches[0][0].ForceBatchesTimestamp) - assert.Equal(t, 0, order[blocks[2].BlockHash][0].Pos) + t.Log("Blocks: ", blocks) + assert.Equal(t, 4, len(blocks)) + assert.Equal(t, 1, len(blocks[3].SequencedBatches)) + assert.Equal(t, common.Hex2Bytes(rawTxs), blocks[3].SequencedBatches[0][1].Transactions) + assert.Equal(t, currentBlock.Time(), blocks[3].SequencedBatches[0][0].Timestamp) + assert.Equal(t, ger, blocks[3].SequencedBatches[0][0].GlobalExitRoot) + assert.Equal(t, auth.From, blocks[3].SequencedBatches[0][0].Coinbase) + assert.Equal(t, auth.From, blocks[3].SequencedBatches[0][0].SequencerAddr) + assert.Equal(t, currentBlock.Time(), blocks[3].SequencedBatches[0][0].MinForcedTimestamp) + assert.Equal(t, 0, order[blocks[3].BlockHash][0].Pos) } func TestVerifyBatchEvent(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, _ := newTestingEnv() + etherman, ethBackend, auth, _, _ := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) rawTxs := "f84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c" - tx := proofofefficiency.ProofOfEfficiencyBatchData{ - GlobalExitRoot: common.Hash{}, - Timestamp: initBlock.Time(), - ForceBatchesTimestamp: []uint64{}, - Transactions: common.Hex2Bytes(rawTxs), + tx := polygonzkevm.PolygonZkEVMBatchData{ + GlobalExitRoot: common.Hash{}, + Timestamp: initBlock.Time(), + MinForcedTimestamp: 0, + Transactions: common.Hex2Bytes(rawTxs), } - _, err = etherman.PoE.SequenceBatches(etherman.auth, []proofofefficiency.ProofOfEfficiencyBatchData{tx}) + _, err = etherman.ZkEVM.SequenceBatches(auth, []polygonzkevm.PolygonZkEVMBatchData{tx}, auth.From) require.NoError(t, err) // Mine the tx in a block ethBackend.Commit() - var ( - proofA = [2]*big.Int{big.NewInt(1), big.NewInt(1)} - proofC = [2]*big.Int{big.NewInt(1), big.NewInt(1)} - proofB = [2][2]*big.Int{proofC, proofC} - ) - _, err = etherman.PoE.VerifyBatch(etherman.auth, common.Hash{}, common.Hash{}, 1, proofA, proofB, proofC) + _, err = etherman.ZkEVM.VerifyBatchesTrustedAggregator(auth, uint64(0), uint64(0), uint64(1), [32]byte{}, [32]byte{}, []byte{}) require.NoError(t, err) // Mine the tx in a block ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) finalBlockNumber := finalBlock.NumberU64() blocks, order, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - - assert.Equal(t, uint64(3), blocks[1].BlockNumber) - assert.Equal(t, uint64(1), blocks[1].VerifiedBatches[0].BatchNumber) - assert.NotEqual(t, common.Address{}, blocks[1].VerifiedBatches[0].Aggregator) - assert.NotEqual(t, common.Hash{}, blocks[1].VerifiedBatches[0].TxHash) - assert.Equal(t, GlobalExitRootsOrder, order[blocks[1].BlockHash][0].Name) - assert.Equal(t, VerifyBatchOrder, order[blocks[1].BlockHash][1].Name) - assert.Equal(t, 0, order[blocks[1].BlockHash][0].Pos) - assert.Equal(t, 0, order[blocks[1].BlockHash][1].Pos) + t.Log("Blocks: ", blocks) + assert.Equal(t, uint64(3), blocks[2].BlockNumber) + assert.Equal(t, uint64(1), blocks[2].VerifiedBatches[0].BatchNumber) + assert.NotEqual(t, common.Address{}, blocks[2].VerifiedBatches[0].Aggregator) + assert.NotEqual(t, common.Hash{}, blocks[2].VerifiedBatches[0].TxHash) + assert.Equal(t, GlobalExitRootsOrder, order[blocks[2].BlockHash][0].Name) + assert.Equal(t, TrustedVerifyBatchOrder, order[blocks[2].BlockHash][1].Name) + assert.Equal(t, 0, order[blocks[2].BlockHash][0].Pos) + assert.Equal(t, 0, order[blocks[2].BlockHash][1].Pos) } func TestSequenceForceBatchesEvent(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, _ := newTestingEnv() + etherman, ethBackend, auth, _, _ := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) - amount, err := etherman.PoE.CalculateForceProverFee(&bind.CallOpts{Pending: false}) + amount, err := etherman.ZkEVM.GetForcedBatchFee(&bind.CallOpts{Pending: false}) require.NoError(t, err) rawTxs := "f84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c" data, err := hex.DecodeString(rawTxs) require.NoError(t, err) - _, err = etherman.PoE.ForceBatch(etherman.auth, data, amount) + _, err = etherman.ZkEVM.ForceBatch(auth, data, amount) require.NoError(t, err) ethBackend.Commit() @@ -252,67 +259,164 @@ func TestSequenceForceBatchesEvent(t *testing.T) { require.NoError(t, err) ethBackend.Commit() - _, err = etherman.PoE.SequenceForceBatches(etherman.auth, 1) + // Now read the event + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + finalBlockNumber := finalBlock.NumberU64() + blocks, _, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) + require.NoError(t, err) + t.Log("Blocks: ", blocks) + + forceBatchData := polygonzkevm.PolygonZkEVMForcedBatchData{ + Transactions: blocks[1].ForcedBatches[0].RawTxsData, + GlobalExitRoot: blocks[1].ForcedBatches[0].GlobalExitRoot, + MinForcedTimestamp: uint64(blocks[1].ForcedBatches[0].ForcedAt.Unix()), + } + _, err = etherman.ZkEVM.SequenceForceBatches(auth, []polygonzkevm.PolygonZkEVMForcedBatchData{forceBatchData}) require.NoError(t, err) ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err = etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) - finalBlockNumber := finalBlock.NumberU64() + finalBlockNumber = finalBlock.NumberU64() blocks, order, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - assert.Equal(t, uint64(4), blocks[1].BlockNumber) - assert.Equal(t, uint64(1), blocks[1].SequencedForceBatches[0].LastBatchSequenced) - assert.Equal(t, uint64(1), blocks[1].SequencedForceBatches[0].ForceBatchNumber) - assert.Equal(t, 0, order[blocks[1].BlockHash][0].Pos) + t.Log("Blocks: ", blocks) + assert.Equal(t, uint64(4), blocks[2].BlockNumber) + assert.Equal(t, uint64(1), blocks[2].SequencedForceBatches[0][0].BatchNumber) + assert.Equal(t, uint64(20), blocks[2].SequencedForceBatches[0][0].MinForcedTimestamp) + assert.Equal(t, 0, order[blocks[2].BlockHash][0].Pos) } func TestSendSequences(t *testing.T) { // Set up testing environment - etherman, ethBackend, _, br := newTestingEnv() + etherman, ethBackend, auth, _, br := newTestingEnv() // Read currentBlock ctx := context.Background() - initBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + initBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) // Make a bridge tx - a := etherman.auth - a.Value = big.NewInt(1000000000000000) - _, err = br.Bridge(a, common.Address{}, 1, a.From, a.Value, []byte{}) + auth.Value = big.NewInt(1000000000000000) + _, err = br.BridgeAsset(auth, 1, auth.From, auth.Value, common.Address{}, true, []byte{}) require.NoError(t, err) ethBackend.Commit() - a.Value = big.NewInt(0) + auth.Value = big.NewInt(0) // Get the last ger ger, err := etherman.GlobalExitRootManager.GetLastGlobalExitRoot(nil) require.NoError(t, err) - currentBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + currentBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + batchL2Data, err := state.EncodeTransactions([]types.Transaction{*tx1}) + require.NoError(t, err) sequence := ethmanTypes.Sequence{ GlobalExitRoot: ger, Timestamp: int64(currentBlock.Time() - 1), - Txs: []types.Transaction{*tx1}, + BatchL2Data: batchL2Data, } - tx, err := etherman.sequenceBatches(etherman.auth, []ethmanTypes.Sequence{sequence}) + tx, err := etherman.sequenceBatches(*auth, []ethmanTypes.Sequence{sequence}) require.NoError(t, err) log.Debug("TX: ", tx.Hash()) ethBackend.Commit() // Now read the event - finalBlock, err := etherman.EtherClient.BlockByNumber(ctx, nil) + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) require.NoError(t, err) finalBlockNumber := finalBlock.NumberU64() blocks, order, err := etherman.GetRollupInfoByBlockRange(ctx, initBlock.NumberU64(), &finalBlockNumber) require.NoError(t, err) - assert.Equal(t, 2, len(blocks)) - assert.Equal(t, 1, len(blocks[1].SequencedBatches)) - assert.Equal(t, currentBlock.Time()-1, blocks[1].SequencedBatches[0][0].Timestamp) - assert.Equal(t, ger, blocks[1].SequencedBatches[0][0].GlobalExitRoot) - assert.Equal(t, []uint64{}, blocks[1].SequencedBatches[0][0].ForceBatchesTimestamp) - assert.Equal(t, 0, order[blocks[1].BlockHash][0].Pos) + t.Log("Blocks: ", blocks) + assert.Equal(t, 3, len(blocks)) + assert.Equal(t, 1, len(blocks[2].SequencedBatches)) + assert.Equal(t, currentBlock.Time()-1, blocks[2].SequencedBatches[0][0].Timestamp) + assert.Equal(t, ger, blocks[2].SequencedBatches[0][0].GlobalExitRoot) + assert.Equal(t, auth.From, blocks[2].SequencedBatches[0][0].Coinbase) + assert.Equal(t, auth.From, blocks[2].SequencedBatches[0][0].SequencerAddr) + assert.Equal(t, uint64(0), blocks[2].SequencedBatches[0][0].MinForcedTimestamp) + assert.Equal(t, 0, order[blocks[2].BlockHash][0].Pos) +} + +func TestGasPrice(t *testing.T) { + // Set up testing environment + etherman, _, _, _, _ := newTestingEnv() + etherscanM := new(etherscanMock) + ethGasStationM := new(ethGasStationMock) + etherman.GasProviders.Providers = []ethereum.GasPricer{etherman.EthClient, etherscanM, ethGasStationM} + ctx := context.Background() + + etherscanM.On("SuggestGasPrice", ctx).Return(big.NewInt(765625003), nil) + ethGasStationM.On("SuggestGasPrice", ctx).Return(big.NewInt(765625002), nil) + gp := etherman.GetL1GasPrice(ctx) + assert.Equal(t, big.NewInt(765625003), gp) + + etherman.GasProviders.Providers = []ethereum.GasPricer{etherman.EthClient, ethGasStationM} + + gp = etherman.GetL1GasPrice(ctx) + assert.Equal(t, big.NewInt(765625002), gp) +} + +func TestErrorEthGasStationPrice(t *testing.T) { + // Set up testing environment + etherman, _, _, _, _ := newTestingEnv() + ethGasStationM := new(ethGasStationMock) + etherman.GasProviders.Providers = []ethereum.GasPricer{etherman.EthClient, ethGasStationM} + ctx := context.Background() + + ethGasStationM.On("SuggestGasPrice", ctx).Return(big.NewInt(0), fmt.Errorf("error getting gasPrice from ethGasStation")) + gp := etherman.GetL1GasPrice(ctx) + assert.Equal(t, big.NewInt(765625001), gp) + + etherscanM := new(etherscanMock) + etherman.GasProviders.Providers = []ethereum.GasPricer{etherman.EthClient, etherscanM, ethGasStationM} + + etherscanM.On("SuggestGasPrice", ctx).Return(big.NewInt(765625003), nil) + gp = etherman.GetL1GasPrice(ctx) + assert.Equal(t, big.NewInt(765625003), gp) +} + +func TestErrorEtherScanPrice(t *testing.T) { + // Set up testing environment + etherman, _, _, _, _ := newTestingEnv() + etherscanM := new(etherscanMock) + ethGasStationM := new(ethGasStationMock) + etherman.GasProviders.Providers = []ethereum.GasPricer{etherman.EthClient, etherscanM, ethGasStationM} + ctx := context.Background() + + etherscanM.On("SuggestGasPrice", ctx).Return(big.NewInt(0), fmt.Errorf("error getting gasPrice from etherscan")) + ethGasStationM.On("SuggestGasPrice", ctx).Return(big.NewInt(765625002), nil) + gp := etherman.GetL1GasPrice(ctx) + assert.Equal(t, big.NewInt(765625002), gp) +} + +func TestGetForks(t *testing.T) { + // Set up testing environment + etherman, _, _, _, _ := newTestingEnv() + ctx := context.Background() + forks, err := etherman.GetForks(ctx, 0) + require.NoError(t, err) + assert.Equal(t, 1, len(forks)) + assert.Equal(t, uint64(1), forks[0].ForkId) + assert.Equal(t, uint64(1), forks[0].FromBatchNumber) + assert.Equal(t, uint64(math.MaxUint64), forks[0].ToBatchNumber) + assert.Equal(t, "v1", forks[0].Version) + // Now read the event + finalBlock, err := etherman.EthClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + finalBlockNumber := finalBlock.NumberU64() + blocks, order, err := etherman.GetRollupInfoByBlockRange(ctx, 0, &finalBlockNumber) + require.NoError(t, err) + t.Logf("Blocks: %+v", blocks) + assert.Equal(t, 1, len(blocks)) + assert.Equal(t, 1, len(blocks[0].ForkIDs)) + assert.Equal(t, 0, order[blocks[0].BlockHash][0].Pos) + assert.Equal(t, ForkIDsOrder, order[blocks[0].BlockHash][0].Name) + assert.Equal(t, uint64(0), blocks[0].ForkIDs[0].BatchNumber) + assert.Equal(t, uint64(1), blocks[0].ForkIDs[0].ForkID) + assert.Equal(t, "v1", blocks[0].ForkIDs[0].Version) } diff --git a/etherman/etherscan/etherscan.go b/etherman/etherscan/etherscan.go new file mode 100644 index 0000000000..b83f75f0fc --- /dev/null +++ b/etherman/etherscan/etherscan.go @@ -0,0 +1,75 @@ +package etherscan + +import ( + "context" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" + + "github.com/0xPolygonHermez/zkevm-node/encoding" +) + +type etherscanResponse struct { + Status string `json:"status"` + Message string `json:"message"` + Result gasPriceEtherscan `json:"result"` +} + +// gasPriceEtherscan definition +type gasPriceEtherscan struct { + LastBlock string `json:"LastBlock"` + SafeGasPrice string `json:"SafeGasPrice"` + ProposeGasPrice string `json:"ProposeGasPrice"` + FastGasPrice string `json:"FastGasPrice"` +} + +// Config structure +type Config struct { + ApiKey string `mapstructure:"ApiKey"` + Url string +} + +// Client for etherscan +type Client struct { + config Config + Http http.Client +} + +// NewEtherscanService is the constructor that creates an etherscanService +func NewEtherscanService(apikey string) *Client { + const url = "https://api.etherscan.io/api?module=gastracker&action=gasoracle&apikey=" + return &Client{ + config: Config{ + Url: url, + ApiKey: apikey, + }, + Http: http.Client{}, + } +} + +// SuggestGasPrice retrieves the gas price estimation from etherscan +func (e *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + var resBody etherscanResponse + url := e.config.Url + e.config.ApiKey + res, err := e.Http.Get(url) + if err != nil { + return big.NewInt(0), err + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + return big.NewInt(0), err + } + if res.StatusCode != http.StatusOK { + return big.NewInt(0), fmt.Errorf("http response is %d", res.StatusCode) + } + // Unmarshal result + err = json.Unmarshal(body, &resBody) + if err != nil { + return big.NewInt(0), fmt.Errorf("Reading body failed: %w", err) + } + fgp, _ := big.NewInt(0).SetString(resBody.Result.FastGasPrice, encoding.Base10) + return new(big.Int).Mul(fgp, big.NewInt(encoding.Gwei)), nil +} diff --git a/etherman/etherscan/etherscan_test.go b/etherman/etherscan/etherscan_test.go new file mode 100644 index 0000000000..c55999b1f7 --- /dev/null +++ b/etherman/etherscan/etherscan_test.go @@ -0,0 +1,39 @@ +package etherscan + +import ( + "context" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stderr"}, + }) +} + +func TestGetGasPrice(t *testing.T) { + ctx := context.Background() + data := `{"status":"1","message":"OK","result":{"LastBlock":"15816910","SafeGasPrice":"10","ProposeGasPrice":"11","FastGasPrice":"55","suggestBaseFee":"9.849758735","gasUsedRatio":"0.779364333333333,0.2434028,0.610012833333333,0.1246597,0.995500566666667"}}` + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, data) + })) + defer svr.Close() + + apiKey := "" + c := NewEtherscanService(apiKey) + c.config.Url = svr.URL + + gp, err := c.SuggestGasPrice(ctx) + require.NoError(t, err) + log.Debug("Etherscan GasPrice: ", gp) + assert.Equal(t, big.NewInt(55000000000), gp) +} diff --git a/etherman/ethgasstation/ethgasstation.go b/etherman/ethgasstation/ethgasstation.go new file mode 100644 index 0000000000..571ca2dfe4 --- /dev/null +++ b/etherman/ethgasstation/ethgasstation.go @@ -0,0 +1,64 @@ +package ethgasstation + +import ( + "context" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" + + "github.com/0xPolygonHermez/zkevm-node/encoding" +) + +type ethGasStationResponse struct { + BaseFee uint64 `json:"baseFee"` + BlockNumber uint64 `json:"blockNumber"` + GasPrice gasPriceEthGasStation `json:"gasPrice"` +} + +// gasPriceEthGasStation definition +type gasPriceEthGasStation struct { + Standard uint64 `json:"standard"` + Instant uint64 `json:"instant"` + Fast uint64 `json:"fast"` +} + +// Client for ethGasStation +type Client struct { + Http http.Client + Url string +} + +// NewEthGasStationService is the constructor that creates an ethGasStationService +func NewEthGasStationService() *Client { + const url = "https://api.ethgasstation.info/api/fee-estimate" + return &Client{ + Http: http.Client{}, + Url: url, + } +} + +// SuggestGasPrice retrieves the gas price estimation from ethGasStation +func (e *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + var resBody ethGasStationResponse + res, err := e.Http.Get(e.Url) + if err != nil { + return big.NewInt(0), err + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + return big.NewInt(0), err + } + if res.StatusCode != http.StatusOK { + return big.NewInt(0), fmt.Errorf("http response is %d", res.StatusCode) + } + // Unmarshal result + err = json.Unmarshal(body, &resBody) + if err != nil { + return big.NewInt(0), fmt.Errorf("Reading body failed: %w", err) + } + fgp := big.NewInt(0).SetUint64(resBody.GasPrice.Instant) + return new(big.Int).Mul(fgp, big.NewInt(encoding.Gwei)), nil +} diff --git a/etherman/ethgasstation/ethgasstation_test.go b/etherman/ethgasstation/ethgasstation_test.go new file mode 100644 index 0000000000..eaffadfdff --- /dev/null +++ b/etherman/ethgasstation/ethgasstation_test.go @@ -0,0 +1,37 @@ +package ethgasstation + +import ( + "context" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stderr"}, + }) +} + +func TestGetGasPrice(t *testing.T) { + ctx := context.Background() + data := `{"baseFee":10,"blockNumber":15817089,"blockTime":11.88,"gasPrice":{"fast":11,"instant":66,"standard":10},"nextBaseFee":10,"priorityFee":{"fast":2,"instant":2,"standard":1}}` + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, data) + })) + defer svr.Close() + c := NewEthGasStationService() + c.Url = svr.URL + + gp, err := c.SuggestGasPrice(ctx) + require.NoError(t, err) + log.Debug("EthGasStation GasPrice: ", gp) + assert.Equal(t, big.NewInt(66000000000), gp) +} diff --git a/etherman/mock_etherscan.go b/etherman/mock_etherscan.go new file mode 100644 index 0000000000..d8e3820968 --- /dev/null +++ b/etherman/mock_etherscan.go @@ -0,0 +1,56 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package etherman + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// etherscanMock is an autogenerated mock type for the GasPricer type +type etherscanMock struct { + mock.Mock +} + +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *etherscanMock) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTnewEtherscanMock interface { + mock.TestingT + Cleanup(func()) +} + +// newEtherscanMock creates a new instance of etherscanMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newEtherscanMock(t mockConstructorTestingTnewEtherscanMock) *etherscanMock { + mock := ðerscanMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/etherman/mock_ethgasstation.go b/etherman/mock_ethgasstation.go new file mode 100644 index 0000000000..ee9f1d5cba --- /dev/null +++ b/etherman/mock_ethgasstation.go @@ -0,0 +1,56 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package etherman + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// ethGasStationMock is an autogenerated mock type for the GasPricer type +type ethGasStationMock struct { + mock.Mock +} + +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *ethGasStationMock) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTnewEthGasStationMock interface { + mock.TestingT + Cleanup(func()) +} + +// newEthGasStationMock creates a new instance of ethGasStationMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newEthGasStationMock(t mockConstructorTestingTnewEthGasStationMock) *ethGasStationMock { + mock := ðGasStationMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/etherman/simulated.go b/etherman/simulated.go index f2600adb85..28e316286f 100644 --- a/etherman/simulated.go +++ b/etherman/simulated.go @@ -5,11 +5,11 @@ import ( "fmt" "math/big" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/bridge" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/globalexitrootmanager" "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/matic" "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/mockverifier" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmbridge" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmglobalexitroot" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" @@ -19,7 +19,11 @@ import ( // NewSimulatedEtherman creates an etherman that uses a simulated blockchain. It's important to notice that the ChainID of the auth // must be 1337. The address that holds the auth will have an initial balance of 10 ETH -func NewSimulatedEtherman(cfg Config, auth *bind.TransactOpts) (etherman *Client, ethBackend *backends.SimulatedBackend, maticAddr common.Address, br *bridge.Bridge, err error) { +func NewSimulatedEtherman(cfg Config, auth *bind.TransactOpts) (etherman *Client, ethBackend *backends.SimulatedBackend, maticAddr common.Address, br *polygonzkevmbridge.Polygonzkevmbridge, err error) { + if auth == nil { + // read only client + return &Client{}, nil, common.Address{}, nil, nil + } // 10000000 ETH in wei balance, _ := new(big.Int).SetString("10000000000000000000000000", 10) //nolint:gomnd address := auth.From @@ -46,32 +50,36 @@ func NewSimulatedEtherman(cfg Config, auth *bind.TransactOpts) (etherman *Client if err != nil { return nil, nil, common.Address{}, nil, err } - const posBridge = 2 + const posBridge = 1 calculatedBridgeAddr := crypto.CreateAddress(auth.From, nonce+posBridge) - const posPoE = 4 + const posPoE = 2 calculatedPoEAddr := crypto.CreateAddress(auth.From, nonce+posPoE) - var genesis [32]byte - exitManagerAddr, _, globalExitRoot, err := globalexitrootmanager.DeployGlobalexitrootmanager(auth, client) + genesis := common.HexToHash("0xfd3434cd8f67e59d73488a2b8da242dd1f02849ea5dd99f0ca22c836c3d5b4a9") // Random value. Needs to be different to 0x0 + exitManagerAddr, _, globalExitRoot, err := polygonzkevmglobalexitroot.DeployPolygonzkevmglobalexitroot(auth, client, calculatedPoEAddr, calculatedBridgeAddr) if err != nil { return nil, nil, common.Address{}, nil, err } - _, err = globalExitRoot.Initialize(auth, calculatedPoEAddr, calculatedBridgeAddr) + bridgeAddr, _, br, err := polygonzkevmbridge.DeployPolygonzkevmbridge(auth, client) if err != nil { return nil, nil, common.Address{}, nil, err } - bridgeAddr, _, br, err := bridge.DeployBridge(auth, client) + poeAddr, _, poe, err := polygonzkevm.DeployPolygonzkevm(auth, client, exitManagerAddr, maticAddr, rollupVerifierAddr, bridgeAddr, 1000, 1) //nolint if err != nil { return nil, nil, common.Address{}, nil, err } - _, err = br.Initialize(auth, 0, exitManagerAddr) + _, err = br.Initialize(auth, 0, exitManagerAddr, poeAddr) if err != nil { return nil, nil, common.Address{}, nil, err } - poeAddr, _, poe, err := proofofefficiency.DeployProofofefficiency(auth, client) - if err != nil { - return nil, nil, common.Address{}, nil, err + + poeParams := polygonzkevm.PolygonZkEVMInitializePackedParameters{ + Admin: auth.From, + TrustedSequencer: auth.From, + PendingStateTimeout: 10000, //nolint:gomnd + TrustedAggregator: auth.From, + TrustedAggregatorTimeout: 10000, //nolint:gomnd } - _, err = poe.Initialize(auth, exitManagerAddr, maticAddr, rollupVerifierAddr, genesis, auth.From, true, "http://localhost", 1000, "L2") //nolint:gomnd + _, err = poe.Initialize(auth, poeParams, genesis, "http://localhost", "L2", "v1") //nolint:gomnd if err != nil { return nil, nil, common.Address{}, nil, err } @@ -95,7 +103,23 @@ func NewSimulatedEtherman(cfg Config, auth *bind.TransactOpts) (etherman *Client if err != nil { return nil, nil, common.Address{}, nil, err } + _, err = poe.ActivateForceBatches(auth) + if err != nil { + return nil, nil, common.Address{}, nil, err + } client.Commit() - return &Client{EtherClient: client, PoE: poe, Matic: maticContract, GlobalExitRootManager: globalExitRoot, SCAddresses: []common.Address{poeAddr, exitManagerAddr}, auth: auth}, client, maticAddr, br, nil + c := &Client{ + EthClient: client, + ZkEVM: poe, + Matic: maticContract, + GlobalExitRootManager: globalExitRoot, + SCAddresses: []common.Address{poeAddr, exitManagerAddr}, + auth: map[common.Address]bind.TransactOpts{}, + } + err = c.AddOrReplaceAuth(*auth) + if err != nil { + return nil, nil, common.Address{}, nil, err + } + return c, client, maticAddr, br, nil } diff --git a/etherman/smartcontracts/abi/mockverifier.abi b/etherman/smartcontracts/abi/mockverifier.abi index b29338d1b8..a7e9032aa2 100644 --- a/etherman/smartcontracts/abi/mockverifier.abi +++ b/etherman/smartcontracts/abi/mockverifier.abi @@ -2,23 +2,13 @@ { "inputs": [ { - "internalType": "uint256[2]", - "name": "a", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2][2]", - "name": "b", - "type": "uint256[2][2]" - }, - { - "internalType": "uint256[2]", - "name": "c", - "type": "uint256[2]" + "internalType": "bytes", + "name": "proof", + "type": "bytes" }, { "internalType": "uint256[1]", - "name": "input", + "name": "pubSignals", "type": "uint256[1]" } ], diff --git a/etherman/smartcontracts/abi/polygonzkevm.abi b/etherman/smartcontracts/abi/polygonzkevm.abi new file mode 100644 index 0000000000..75e2894369 --- /dev/null +++ b/etherman/smartcontracts/abi/polygonzkevm.abi @@ -0,0 +1,1709 @@ +[ + { + "inputs": [ + { + "internalType": "contract IPolygonZkEVMGlobalExitRoot", + "name": "_globalExitRootManager", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "_matic", + "type": "address" + }, + { + "internalType": "contract IVerifierRollup", + "name": "_rollupVerifier", + "type": "address" + }, + { + "internalType": "contract IPolygonZkEVMBridge", + "name": "_bridgeAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "_chainID", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_forkID", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BatchAlreadyVerified", + "type": "error" + }, + { + "inputs": [], + "name": "BatchNotSequencedOrNotSequenceEnd", + "type": "error" + }, + { + "inputs": [], + "name": "ExceedMaxVerifyBatches", + "type": "error" + }, + { + "inputs": [], + "name": "FinalNumBatchBelowLastVerifiedBatch", + "type": "error" + }, + { + "inputs": [], + "name": "FinalNumBatchDoesNotMatchPendingState", + "type": "error" + }, + { + "inputs": [], + "name": "FinalPendingStateNumInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchTimeoutNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesAlreadyActive", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesOverflow", + "type": "error" + }, + { + "inputs": [], + "name": "ForcedDataDoesNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalExitRootNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "HaltTimeoutNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "InitNumBatchAboveLastVerifiedBatch", + "type": "error" + }, + { + "inputs": [], + "name": "InitNumBatchDoesNotMatchPendingState", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeBatchTimeTarget", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeForceBatchTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeMultiplierBatchFee", + "type": "error" + }, + { + "inputs": [], + "name": "NewAccInputHashDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "NewPendingStateTimeoutMustBeLower", + "type": "error" + }, + { + "inputs": [], + "name": "NewStateRootNotInsidePrime", + "type": "error" + }, + { + "inputs": [], + "name": "NewTrustedAggregatorTimeoutMustBeLower", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughMaticAmount", + "type": "error" + }, + { + "inputs": [], + "name": "OldAccInputHashDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "OldStateRootDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyNotEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPendingAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTrustedAggregator", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTrustedSequencer", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateNotConsolidable", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateTimeoutExceedHaltAggregationTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "SequenceZeroBatches", + "type": "error" + }, + { + "inputs": [], + "name": "SequencedTimestampBelowForcedTimestamp", + "type": "error" + }, + { + "inputs": [], + "name": "SequencedTimestampInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "StoredRootMustBeDifferentThanNewRoot", + "type": "error" + }, + { + "inputs": [], + "name": "TransactionsLengthAboveMax", + "type": "error" + }, + { + "inputs": [], + "name": "TrustedAggregatorTimeoutExceedHaltAggregationTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "TrustedAggregatorTimeoutNotExpired", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AcceptAdminRole", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ActivateForceBatches", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "pendingStateNum", + "type": "uint64" + } + ], + "name": "ConsolidatePendingState", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "forceBatchNum", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "lastGlobalExitRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "sequencer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + } + ], + "name": "ForceBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "OverridePendingState", + "type": "event" + }, + { + "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": false, + "internalType": "bytes32", + "name": "storedStateRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "provedStateRoot", + "type": "bytes32" + } + ], + "name": "ProveNonDeterministicPendingState", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + } + ], + "name": "SequenceBatches", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + } + ], + "name": "SequenceForceBatches", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newforceBatchTimeout", + "type": "uint64" + } + ], + "name": "SetForceBatchTimeout", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "newMultiplierBatchFee", + "type": "uint16" + } + ], + "name": "SetMultiplierBatchFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newPendingStateTimeout", + "type": "uint64" + } + ], + "name": "SetPendingStateTimeout", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newTrustedAggregator", + "type": "address" + } + ], + "name": "SetTrustedAggregator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newTrustedAggregatorTimeout", + "type": "uint64" + } + ], + "name": "SetTrustedAggregatorTimeout", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newTrustedSequencer", + "type": "address" + } + ], + "name": "SetTrustedSequencer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newTrustedSequencerURL", + "type": "string" + } + ], + "name": "SetTrustedSequencerURL", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newVerifyBatchTimeTarget", + "type": "uint64" + } + ], + "name": "SetVerifyBatchTimeTarget", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "TransferAdminRole", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "name": "UpdateZkEVMVersion", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "VerifyBatches", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "numBatch", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "VerifyBatchesTrustedAggregator", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdminRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequencedBatchNum", + "type": "uint64" + } + ], + "name": "activateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "activateForceBatches", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "batchNumToStateRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeAddress", + "outputs": [ + { + "internalType": "contract IPolygonZkEVMBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "calculateRewardPerBatch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainID", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newStateRoot", + "type": "uint256" + } + ], + "name": "checkStateRootInsidePrime", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "pendingStateNum", + "type": "uint64" + } + ], + "name": "consolidatePendingState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deactivateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maticAmount", + "type": "uint256" + } + ], + "name": "forceBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "forceBatchTimeout", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "forcedBatches", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "forkID", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getForcedBatchFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "oldStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + } + ], + "name": "getInputSnarkBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastVerifiedBatch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootManager", + "outputs": [ + { + "internalType": "contract IPolygonZkEVMGlobalExitRoot", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "trustedSequencer", + "type": "address" + }, + { + "internalType": "uint64", + "name": "pendingStateTimeout", + "type": "uint64" + }, + { + "internalType": "address", + "name": "trustedAggregator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "trustedAggregatorTimeout", + "type": "uint64" + } + ], + "internalType": "struct PolygonZkEVM.InitializePackedParameters", + "name": "initializePackedParameters", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "genesisRoot", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "_trustedSequencerURL", + "type": "string" + }, + { + "internalType": "string", + "name": "_networkName", + "type": "string" + }, + { + "internalType": "string", + "name": "_version", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isEmergencyState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isForcedBatchDisallowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "pendingStateNum", + "type": "uint64" + } + ], + "name": "isPendingStateConsolidable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastBatchSequenced", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastForceBatch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastForceBatchSequenced", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPendingState", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPendingStateConsolidated", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimestamp", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastVerifiedBatch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "matic", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "multiplierBatchFee", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "networkName", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "initPendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalPendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + } + ], + "name": "overridePendingState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingStateTimeout", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pendingStateTransitions", + "outputs": [ + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "exitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "initPendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalPendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + } + ], + "name": "proveNonDeterministicPendingState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rollupVerifier", + "outputs": [ + { + "internalType": "contract IVerifierRollup", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "globalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minForcedTimestamp", + "type": "uint64" + } + ], + "internalType": "struct PolygonZkEVM.BatchData[]", + "name": "batches", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "l2Coinbase", + "type": "address" + } + ], + "name": "sequenceBatches", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "globalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "minForcedTimestamp", + "type": "uint64" + } + ], + "internalType": "struct PolygonZkEVM.ForcedBatchData[]", + "name": "batches", + "type": "tuple[]" + } + ], + "name": "sequenceForceBatches", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "sequencedBatches", + "outputs": [ + { + "internalType": "bytes32", + "name": "accInputHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "sequencedTimestamp", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "previousLastBatchSequenced", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newforceBatchTimeout", + "type": "uint64" + } + ], + "name": "setForceBatchTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "newMultiplierBatchFee", + "type": "uint16" + } + ], + "name": "setMultiplierBatchFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newPendingStateTimeout", + "type": "uint64" + } + ], + "name": "setPendingStateTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTrustedAggregator", + "type": "address" + } + ], + "name": "setTrustedAggregator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newTrustedAggregatorTimeout", + "type": "uint64" + } + ], + "name": "setTrustedAggregatorTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTrustedSequencer", + "type": "address" + } + ], + "name": "setTrustedSequencer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newTrustedSequencerURL", + "type": "string" + } + ], + "name": "setTrustedSequencerURL", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newVerifyBatchTimeTarget", + "type": "uint64" + } + ], + "name": "setVerifyBatchTimeTarget", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "transferAdminRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedAggregator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedAggregatorTimeout", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedSequencer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedSequencerURL", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "verifyBatchTimeTarget", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "pendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + } + ], + "name": "verifyBatches", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "pendingStateNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + } + ], + "name": "verifyBatchesTrustedAggregator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/etherman/smartcontracts/abi/bridge.abi b/etherman/smartcontracts/abi/polygonzkevmbridge.abi similarity index 61% rename from etherman/smartcontracts/abi/bridge.abi rename to etherman/smartcontracts/abi/polygonzkevmbridge.abi index d099622165..f7547c006f 100644 --- a/etherman/smartcontracts/abi/bridge.abi +++ b/etherman/smartcontracts/abi/polygonzkevmbridge.abi @@ -1,7 +1,93 @@ [ + { + "inputs": [], + "name": "AlreadyClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountDoesNotMatchMsgValue", + "type": "error" + }, + { + "inputs": [], + "name": "DestinationNetworkInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "EtherTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalExitRootInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSmtProof", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleTreeFull", + "type": "error" + }, + { + "inputs": [], + "name": "MessageFailed", + "type": "error" + }, + { + "inputs": [], + "name": "MsgValueNotZero", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSpender", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyNotEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPolygonZkEVM", + "type": "error" + }, { "anonymous": false, "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, { "indexed": false, "internalType": "uint32", @@ -11,7 +97,7 @@ { "indexed": false, "internalType": "address", - "name": "originTokenAddress", + "name": "originAddress", "type": "address" }, { @@ -66,7 +152,7 @@ { "indexed": false, "internalType": "address", - "name": "originTokenAddress", + "name": "originAddress", "type": "address" }, { @@ -85,6 +171,18 @@ "name": "ClaimEvent", "type": "event" }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateDeactivated", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -118,6 +216,12 @@ "internalType": "address", "name": "wrappedTokenAddress", "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" } ], "name": "NewWrappedToken", @@ -125,22 +229,107 @@ }, { "inputs": [], - "name": "MAINNET_NETWORK_ID", - "outputs": [ + "name": "activateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { "internalType": "uint32", - "name": "", + "name": "destinationNetwork", "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "permitData", + "type": "bytes" } ], - "stateMutability": "view", + "name": "bridgeAsset", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, { "internalType": "address", - "name": "token", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "bridgeMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[32]", + "name": "smtProof", + "type": "bytes32[32]" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "mainnetExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "rollupExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", "type": "address" }, { @@ -160,21 +349,21 @@ }, { "internalType": "bytes", - "name": "permitData", + "name": "metadata", "type": "bytes" } ], - "name": "bridge", + "name": "claimAsset", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "bytes32[]", + "internalType": "bytes32[32]", "name": "smtProof", - "type": "bytes32[]" + "type": "bytes32[32]" }, { "internalType": "uint32", @@ -198,7 +387,7 @@ }, { "internalType": "address", - "name": "originTokenAddress", + "name": "originAddress", "type": "address" }, { @@ -222,7 +411,7 @@ "type": "bytes" } ], - "name": "claim", + "name": "claimMessage", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -235,17 +424,24 @@ "type": "uint256" } ], - "name": "claimNullifier", + "name": "claimedBitMap", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deactivateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "depositCount", @@ -274,6 +470,11 @@ }, { "inputs": [ + { + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, { "internalType": "uint32", "name": "originNetwork", @@ -281,7 +482,7 @@ }, { "internalType": "address", - "name": "originTokenAddress", + "name": "originAddress", "type": "address" }, { @@ -345,7 +546,7 @@ "name": "globalExitRootManager", "outputs": [ { - "internalType": "contract IGlobalExitRootManager", + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", "name": "", "type": "address" } @@ -361,9 +562,14 @@ "type": "uint32" }, { - "internalType": "contract IGlobalExitRootManager", + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", "name": "_globalExitRootManager", "type": "address" + }, + { + "internalType": "address", + "name": "_polygonZkEVMaddress", + "type": "address" } ], "name": "initialize", @@ -371,9 +577,41 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "isClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], - "name": "networkID", + "name": "isEmergencyState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdatedDepositCount", "outputs": [ { "internalType": "uint32", @@ -385,19 +623,21 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "networkID", + "outputs": [ { "internalType": "uint32", - "name": "originNetwork", + "name": "", "type": "uint32" - }, - { - "internalType": "address", - "name": "originTokenAddress", - "type": "address" } ], - "name": "precalculatedWrapperAddress", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "polygonZkEVMaddress", "outputs": [ { "internalType": "address", @@ -409,8 +649,34 @@ "type": "function" }, { - "inputs": [], - "name": "tokenImplementation", + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + } + ], + "name": "precalculatedWrapperAddress", "outputs": [ { "internalType": "address", @@ -440,6 +706,13 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "updateGlobalExitRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -448,14 +721,14 @@ "type": "bytes32" }, { - "internalType": "bytes32[]", + "internalType": "bytes32[32]", "name": "smtProof", - "type": "bytes32[]" + "type": "bytes32[32]" }, { - "internalType": "uint64", + "internalType": "uint32", "name": "index", - "type": "uint64" + "type": "uint32" }, { "internalType": "bytes32", diff --git a/etherman/smartcontracts/abi/globalexitrootmanager.abi b/etherman/smartcontracts/abi/polygonzkevmglobalexitroot.abi similarity index 79% rename from etherman/smartcontracts/abi/globalexitrootmanager.abi rename to etherman/smartcontracts/abi/polygonzkevmglobalexitroot.abi index 5e21783242..85f181413d 100644 --- a/etherman/smartcontracts/abi/globalexitrootmanager.abi +++ b/etherman/smartcontracts/abi/polygonzkevmglobalexitroot.abi @@ -1,26 +1,28 @@ [ { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "address", + "name": "_rollupAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_bridgeAddress", + "type": "address" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OnlyAllowedContracts", + "type": "error" }, { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "globalExitRootNum", - "type": "uint256" - }, { "indexed": true, "internalType": "bytes32", @@ -82,37 +84,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "_rollupAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_bridgeAddress", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastGlobalExitRootNum", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "lastMainnetExitRoot", diff --git a/etherman/smartcontracts/abi/proofofefficiency.abi b/etherman/smartcontracts/abi/proofofefficiency.abi deleted file mode 100644 index 0a404c6447..0000000000 --- a/etherman/smartcontracts/abi/proofofefficiency.abi +++ /dev/null @@ -1,631 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "forceBatchNum", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "lastGlobalExitRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "sequencer", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "transactions", - "type": "bytes" - } - ], - "name": "ForceBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - } - ], - "name": "SequenceBatches", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - } - ], - "name": "SequenceForceBatches", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "newForceBatchAllowed", - "type": "bool" - } - ], - "name": "SetForceBatchAllowed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newTrustedSequencer", - "type": "address" - } - ], - "name": "SetTrustedSequencer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "newTrustedSequencerURL", - "type": "string" - } - ], - "name": "SetTrustedSequencerURL", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "VerifyBatch", - "type": "event" - }, - { - "inputs": [], - "name": "FORCE_BATCH_TIMEOUT", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_BATCH_LENGTH", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "TRUSTED_SEQUENCER_FEE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "calculateForceProverFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "chainID", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentLocalExitRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentStateRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "transactions", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maticAmount", - "type": "uint256" - } - ], - "name": "forceBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "forceBatchAllowed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "forcedBatches", - "outputs": [ - { - "internalType": "bytes32", - "name": "batchHashData", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "maticFee", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "minTimestamp", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "globalExitRootManager", - "outputs": [ - { - "internalType": "contract IGlobalExitRootManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IGlobalExitRootManager", - "name": "_globalExitRootManager", - "type": "address" - }, - { - "internalType": "contract IERC20Upgradeable", - "name": "_matic", - "type": "address" - }, - { - "internalType": "contract IVerifierRollup", - "name": "_rollupVerifier", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "genesisRoot", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_trustedSequencer", - "type": "address" - }, - { - "internalType": "bool", - "name": "_forceBatchAllowed", - "type": "bool" - }, - { - "internalType": "string", - "name": "_trustedSequencerURL", - "type": "string" - }, - { - "internalType": "uint64", - "name": "_chainID", - "type": "uint64" - }, - { - "internalType": "string", - "name": "_networkName", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastBatchSequenced", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastForceBatch", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastForceBatchSequenced", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastTimestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastVerifiedBatch", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "matic", - "outputs": [ - { - "internalType": "contract IERC20Upgradeable", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "networkName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rollupVerifier", - "outputs": [ - { - "internalType": "contract IVerifierRollup", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "transactions", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "globalExitRoot", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64[]", - "name": "forceBatchesTimestamp", - "type": "uint64[]" - } - ], - "internalType": "struct ProofOfEfficiency.BatchData[]", - "name": "batches", - "type": "tuple[]" - } - ], - "name": "sequenceBatches", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "numForcedBatches", - "type": "uint64" - } - ], - "name": "sequenceForceBatches", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "sequencedBatches", - "outputs": [ - { - "internalType": "bytes32", - "name": "batchHashData", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "forceBatchNum", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "newForceBatchAllowed", - "type": "bool" - } - ], - "name": "setForceBatchAllowed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newTrustedSequencer", - "type": "address" - } - ], - "name": "setTrustedSequencer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "newTrustedSequencerURL", - "type": "string" - } - ], - "name": "setTrustedSequencerURL", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedSequencer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "trustedSequencerURL", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "internalType": "uint256[2]", - "name": "proofA", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2][2]", - "name": "proofB", - "type": "uint256[2][2]" - }, - { - "internalType": "uint256[2]", - "name": "proofC", - "type": "uint256[2]" - } - ], - "name": "verifyBatch", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] \ No newline at end of file diff --git a/etherman/smartcontracts/bin/bridge.bin b/etherman/smartcontracts/bin/bridge.bin deleted file mode 100644 index 4941f282c8..0000000000 --- a/etherman/smartcontracts/bin/bridge.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50614adb806100206000396000f3fe608060405260043610620001075760003560e01c80635d5d326f1162000095578063bab161bf1162000060578063bab161bf1462000414578063d02103ca1462000449578063e73758811462000478578063ed6be5c914620004ac57600080fd5b80635d5d326f146200035e57806381b1c17414620003835780638624c35c14620003ca578063b7e6a7d414620003ef57600080fd5b80633ae0504711620000d65780633ae05047146200023a5780633da816821462000252578063508935f814620002885780635a64a1da14620002a157600080fd5b806322e95f2c146200010c5780632dfdf0b5146200015b5780632f3a3d5d1462000182578063318aee3d14620001b1575b600080fd5b3480156200011957600080fd5b50620001316200012b3660046200278e565b620004c3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200016857600080fd5b506200017360415481565b60405190815260200162000152565b3480156200018f57600080fd5b50604754620001319073ffffffffffffffffffffffffffffffffffffffff1681565b348015620001be57600080fd5b5062000208620001d0366004620027ca565b60456020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff90911660208301520162000152565b3480156200024757600080fd5b506200017362000566565b3480156200025f57600080fd5b506200027762000271366004620028e9565b62000640565b604051901515815260200162000152565b6200029f6200029936600462002957565b62000740565b005b348015620002ae57600080fd5b5062000173620002c036600462002a13565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e098891b81166020808401919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006060998a1b811660248501529790991b1660388201529390951b909316603c830152605082015260708082019290925282518082039092018252609001909152805191012090565b3480156200036b57600080fd5b506200029f6200037d36600462002b2b565b62000d2a565b3480156200039057600080fd5b5062000131620003a236600462002c12565b60446020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620003d757600080fd5b506200029f620003e93660046200278e565b620017d9565b348015620003fc57600080fd5b50620001316200040e3660046200278e565b62001a57565b3480156200042157600080fd5b50604254620004339063ffffffff1681565b60405163ffffffff909116815260200162000152565b3480156200045657600080fd5b50604654620001319073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200048557600080fd5b50620002776200049736600462002c12565b60436020526000908152604090205460ff1681565b348015620004b957600080fd5b5062000433600081565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166024830152825160188184030181526038909201835281519181019190912060009081526044909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b6041546000908190815b6020811015620006385781600116600103620005d057600181602081106200059c576200059c62002c2c565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925062000614565b8260218260208110620005e757620005e762002c2c565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b6200062160028362002c8a565b9150806200062f8162002cc6565b91505062000570565b509092915050565b60008467ffffffffffffffff8416825b6020811015620007335781600116600103620006bd578681815181106200067b576200067b62002c2c565b6020026020010151836040516020016200069f929190918252602082015260400190565b6040516020818303038152906040528051906020012092506200070f565b82878281518110620006d357620006d362002c2c565b6020026020010151604051602001620006f6929190918252602082015260400190565b6040516020818303038152906040528051906020012092505b6200071c60028362002c8a565b9150806200072a8162002cc6565b91505062000650565b5050909114949350505050565b60425463ffffffff90811690861603620007e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4272696467653a3a6272696467653a2044455354494e4154494f4e5f43414e5460448201527f5f42455f495453454c460000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600080606073ffffffffffffffffffffffffffffffffffffffff89166200089d5785341462000893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4272696467653a3a6272696467653a20414d4f554e545f444f45535f4e4f545f60448201527f4d415443485f4d53475f56414c554500000000000000000000000000000000006064820152608401620007d8565b6000915062000bb1565b73ffffffffffffffffffffffffffffffffffffffff808a1660009081526045602090815260409182902082518084019093525463ffffffff81168352640100000000900490921691810182905290156200099e576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810188905273ffffffffffffffffffffffffffffffffffffffff8b1690639dc29fac906044016020604051808303816000875af115801562000965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200098b919062002d01565b5060208101518151909450925062000baf565b8415620009b357620009b38a88888862001b20565b620009d773ffffffffffffffffffffffffffffffffffffffff8b1633308a62001f4b565b899350604260009054906101000a900463ffffffff1692508973ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000a3b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000a83919081019062002da0565b8a73ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000acf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000b17919081019062002da0565b8b73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000b63573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b89919062002de9565b60405160200162000b9d9392919062002e55565b60405160208183030381529060405291505b505b7ff0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a82848a8a8a8660415460405162000bf0979695949392919062002e92565b60405180910390a18051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e087811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608a811b82166024860152918f901b90921660388401528c901b16603c820152605081018a9052607080820193909352815180820390930183526090019052805191012062000ca4906200202f565b60465473ffffffffffffffffffffffffffffffffffffffff166333d6247d62000ccc62000566565b6040518263ffffffff1660e01b815260040162000ceb91815260200190565b600060405180830381600087803b15801562000d0657600080fd5b505af115801562000d1b573d6000803e3d6000fd5b50505050505050505050505050565b63ffffffff891660009081526043602052604090205460ff161562000dac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4272696467653a3a636c61696d3a20414c52454144595f434c41494d454400006044820152606401620007d8565b6046546040805160208082018c90528183018b9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915273ffffffffffffffffffffffffffffffffffffffff9091169063257b3632906084016020604051808303816000875af115801562000e45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e6b919062002eff565b60000362000efc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4272696467653a3a636c61696d3a20474c4f42414c5f455849545f524f4f545f60448201527f444f45535f4e4f545f4d415443480000000000000000000000000000000000006064820152608401620007d8565b60425463ffffffff85811691161462000f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4272696467653a3a636c61696d3a2044455354494e4154494f4e5f4e4554574f60448201527f524b5f444f45535f4e4f545f4d415443480000000000000000000000000000006064820152608401620007d8565b60425463ffffffff16620010c9578051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200105b908b8b63ffffffff168a62000640565b620010c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b620011e6565b8051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200117e908b8b63ffffffff168b62000640565b620011e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b63ffffffff8916600090815260436020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905573ffffffffffffffffffffffffffffffffffffffff851662001357576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff851690849060405162001279919062002f19565b60006040518083038185875af1925050503d8060008114620012b8576040519150601f19603f3d011682016040523d82523d6000602084013e620012bd565b606091505b505090508062001350576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4272696467653a3a636c61696d3a204554485f5452414e534645525f4641494c60448201527f45440000000000000000000000000000000000000000000000000000000000006064820152608401620007d8565b5062001762565b60425463ffffffff9081169087160362001394576200138e73ffffffffffffffffffffffffffffffffffffffff86168484620021a8565b62001762565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152604490935291205490915073ffffffffffffffffffffffffffffffffffffffff1680620016c1576047546000906200147f9073ffffffffffffffffffffffffffffffffffffffff168462002200565b90506000806000868060200190518101906200149c919062002f37565b9250925092508373ffffffffffffffffffffffffffffffffffffffff16636c9452218484848d8d6040518663ffffffff1660e01b8152600401620014e595949392919062002fb8565b600060405180830381600087803b1580156200150057600080fd5b505af115801562001515573d6000803e3d6000fd5b50505050836044600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808d63ffffffff1681526020018c73ffffffffffffffffffffffffffffffffffffffff16815250604560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507fccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d598c8c86604051620016af9392919063ffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff918216602084015216604082015260600190565b60405180910390a1505050506200175f565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528216906340c10f19906044016020604051808303816000875af115801562001737573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200175d919062002d01565b505b50505b6040805163ffffffff8b811682528816602082015273ffffffffffffffffffffffffffffffffffffffff87811682840152851660608201526080810184905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a150505050505050505050565b600054610100900460ff1615808015620017fa5750600054600160ff909116105b80620018165750303b15801562001816575060005460ff166001145b620018a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620007d8565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200190357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b604280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8516179055604680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055604051620019819062002736565b604051809103906000f0801580156200199e573d6000803e3d6000fd5b50604780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055620019ee620022e0565b801562001a5257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660248201526000908190603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012060475490915062001b189073ffffffffffffffffffffffffffffffffffffffff168262002428565b949350505050565b600062001b6383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620024ac92505050565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fd505accf000000000000000000000000000000000000000000000000000000001462001c12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696467653a3a5f7065726d69743a204e4f545f56414c49445f43414c4c006044820152606401620007d8565b600080808080808062001c29896004818d62003018565b81019062001c38919062003044565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001d03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4272696467653a3a5f7065726d69743a205045524d49545f4f574e45525f4d5560448201527f53545f42455f5448455f53454e444552000000000000000000000000000000006064820152608401620007d8565b73ffffffffffffffffffffffffffffffffffffffff8616301462001daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696467653a3a5f7065726d69743a205350454e4445525f4d5553545f424560448201527f5f544849530000000000000000000000000000000000000000000000000000006064820152608401620007d8565b8a851462001e3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4272696467653a3a5f7065726d69743a205045524d49545f414d4f554e545f4460448201527f4f45535f4e4f545f4d41544348000000000000000000000000000000000000006064820152608401620007d8565b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162001ef6919062002f19565b6000604051808303816000865af19150503d806000811462001f35576040519150601f19603f3d011682016040523d82523d6000602084013e62001f3a565b606091505b505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620020299085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620024b3565b50505050565b8060016200204060206002620031f5565b6200204c919062003203565b60415410620020de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4465706f736974436f6e74726163743a5f6465706f7369743a204d45524b4c4560448201527f5f545245455f46554c4c000000000000000000000000000000000000000000006064820152608401620007d8565b600160416000828254620020f391906200321d565b909155505060415460005b60208110156200219d5781600116600103620021335782600182602081106200212b576200212b62002c2c565b015550505050565b6001816020811062002149576200214962002c2c565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925060028262002186919062002c8a565b915080620021948162002cc6565b915050620020fe565b5062001a5262003238565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001a529084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640162001fa6565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f591505073ffffffffffffffffffffffffffffffffffffffff811662000560576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401620007d8565b600054610100900460ff1662002379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620007d8565b60005b6200238a6001602062003203565b811015620024255760218160208110620023a857620023a862002c2c565b015460218260208110620023c057620023c062002c2c565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206021826001620023fb91906200321d565b602081106200240e576200240e62002c2c565b0155806200241c8162002cc6565b9150506200237c565b50565b6000620024a58383306040517f3d602d80600a3d3981f3363d3d373d3d3d363d730000000000000000000000008152606093841b60148201527f5af43d82803e903d91602b57fd5bf3ff000000000000000000000000000000006028820152921b6038830152604c8201526037808220606c830152605591012090565b9392505050565b6020015190565b600062002517826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620025c69092919063ffffffff16565b80519091501562001a52578080602001905181019062002538919062002d01565b62001a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620007d8565b606062001b1884846000858573ffffffffffffffffffffffffffffffffffffffff85163b62002652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620007d8565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516200267d919062002f19565b60006040518083038185875af1925050503d8060008114620026bc576040519150601f19603f3d011682016040523d82523d6000602084013e620026c1565b606091505b5091509150620026d3828286620026de565b979650505050505050565b60608315620026ef575081620024a5565b825115620027005782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007d8919062003267565b611829806200327d83390190565b803563ffffffff811681146200275957600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146200242557600080fd5b803562002759816200275e565b60008060408385031215620027a257600080fd5b620027ad8362002744565b91506020830135620027bf816200275e565b809150509250929050565b600060208284031215620027dd57600080fd5b8135620024a5816200275e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620028635762002863620027ea565b604052919050565b600082601f8301126200287d57600080fd5b8135602067ffffffffffffffff8211156200289c576200289c620027ea565b8160051b620028ad82820162002819565b9283528481018201928281019087851115620028c857600080fd5b83870192505b84831015620026d357823582529183019190830190620028ce565b600080600080608085870312156200290057600080fd5b84359350602085013567ffffffffffffffff808211156200292057600080fd5b6200292e888389016200286b565b94506040870135915080821682146200294657600080fd5b509396929550929360600135925050565b60008060008060008060a087890312156200297157600080fd5b86356200297e816200275e565b95506200298e6020880162002744565b94506040870135620029a0816200275e565b935060608701359250608087013567ffffffffffffffff80821115620029c557600080fd5b818901915089601f830112620029da57600080fd5b813581811115620029ea57600080fd5b8a6020828501011115620029fd57600080fd5b6020830194508093505050509295509295509295565b60008060008060008060c0878903121562002a2d57600080fd5b62002a388762002744565b9550602087013562002a4a816200275e565b945062002a5a6040880162002744565b9350606087013562002a6c816200275e565b9598949750929560808101359460a0909101359350915050565b600067ffffffffffffffff82111562002aa35762002aa3620027ea565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002ae157600080fd5b813562002af862002af28262002a86565b62002819565b81815284602083860101111562002b0e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d03121562002b4c57600080fd5b8a3567ffffffffffffffff8082111562002b6557600080fd5b62002b738e838f016200286b565b9b5062002b8360208e0162002744565b9a5060408d0135995060608d0135985062002ba160808e0162002744565b975062002bb160a08e0162002781565b965062002bc160c08e0162002744565b955062002bd160e08e0162002781565b94506101008d013593506101208d013591508082111562002bf157600080fd5b5062002c008d828e0162002acf565b9150509295989b9194979a5092959850565b60006020828403121562002c2557600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008262002cc1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002cfa5762002cfa62002c5b565b5060010190565b60006020828403121562002d1457600080fd5b81518015158114620024a557600080fd5b60005b8381101562002d4257818101518382015260200162002d28565b83811115620020295750506000910152565b600082601f83011262002d6657600080fd5b815162002d7762002af28262002a86565b81815284602083860101111562002d8d57600080fd5b62001b1882602083016020870162002d25565b60006020828403121562002db357600080fd5b815167ffffffffffffffff81111562002dcb57600080fd5b62001b188482850162002d54565b60ff811681146200242557600080fd5b60006020828403121562002dfc57600080fd5b8151620024a58162002dd9565b6000815180845262002e2381602086016020860162002d25565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062002e6a606083018662002e09565b828103602084015262002e7e818662002e09565b91505060ff83166040830152949350505050565b600063ffffffff808a16835273ffffffffffffffffffffffffffffffffffffffff808a166020850152818916604085015280881660608501525085608084015260e060a084015262002ee860e084018662002e09565b915080841660c08401525098975050505050505050565b60006020828403121562002f1257600080fd5b5051919050565b6000825162002f2d81846020870162002d25565b9190910192915050565b60008060006060848603121562002f4d57600080fd5b835167ffffffffffffffff8082111562002f6657600080fd5b62002f748783880162002d54565b9450602086015191508082111562002f8b57600080fd5b5062002f9a8682870162002d54565b925050604084015162002fad8162002dd9565b809150509250925092565b60a08152600062002fcd60a083018862002e09565b828103602084015262002fe1818862002e09565b60ff969096166040840152505073ffffffffffffffffffffffffffffffffffffffff92909216606083015260809091015292915050565b600080858511156200302957600080fd5b838611156200303757600080fd5b5050820193919092039150565b600080600080600080600060e0888a0312156200306057600080fd5b87356200306d816200275e565b965060208801356200307f816200275e565b9550604088013594506060880135935060808801356200309f8162002dd9565b9699959850939692959460a0840135945060c09093013592915050565b600181815b808511156200311b57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620030ff57620030ff62002c5b565b808516156200310d57918102915b93841c9390800290620030c1565b509250929050565b600082620031345750600162000560565b81620031435750600062000560565b81600181146200315c5760028114620031675762003187565b600191505062000560565b60ff8411156200317b576200317b62002c5b565b50506001821b62000560565b5060208310610133831016604e8410600b8410161715620031ac575081810a62000560565b620031b88383620030bc565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620031ed57620031ed62002c5b565b029392505050565b6000620024a5838362003123565b60008282101562003218576200321862002c5b565b500390565b6000821982111562003233576200323362002c5b565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b602081526000620024a5602083018462002e0956fe60806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200013d60201b6200080a1760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b506200014c565b6001600160a01b03163b151590565b6116cd806200015c6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80636c94522111610097578063a3c573eb11610066578063a3c573eb1461021c578063a457c2d714610261578063a9059cbb14610274578063dd62ed3e1461028757600080fd5b80636c945221146101b657806370a08231146101cb57806395d89b41146102015780639dc29fac1461020957600080fd5b806323b872dd116100d357806323b872dd1461014d578063313ce56714610160578063395093511461019057806340c10f19146101a357600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b6101026102cd565b60405161010f91906111c0565b60405180910390f35b61012b61012636600461125c565b61035f565b604051901515815260200161010f565b6035545b60405190815260200161010f565b61012b61015b366004611286565b610377565b60655474010000000000000000000000000000000000000000900460ff1660405160ff909116815260200161010f565b61012b61019e36600461125c565b61039b565b61012b6101b136600461125c565b6103e7565b6101c96101c436600461139c565b610483565b005b61013f6101d9366004611431565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61010261068e565b61012b61021736600461125c565b61069d565b60655461023c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010f565b61012b61026f36600461125c565b61072b565b61012b61028236600461125c565b6107fc565b61013f610295366004611453565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102dc90611486565b80601f016020809104026020016040519081016040528092919081815260200182805461030890611486565b80156103555780601f1061032a57610100808354040283529160200191610355565b820191906000526020600020905b81548152906001019060200180831161033857829003601f168201915b5050505050905090565b60003361036d818585610826565b5060019392505050565b6000336103858582856109da565b610390858585610ab1565b506001949350505050565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061036d90829086906103e2908790611508565b610826565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f42524944474500000000000000000060448201526064015b60405180910390fd5b61047a8383610d64565b50600192915050565b600054610100900460ff16158080156104a35750600054600160ff909116105b806104bd5750303b1580156104bd575060005460ff166001145b610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610467565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105b18686610e85565b606580547fffffffffffffffffffffff00000000000000000000000000000000000000000016337fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16177401000000000000000000000000000000000000000060ff8716021790556106238383610d64565b801561068657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6060603780546102dc90611486565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f4252494447450000000000000000006044820152606401610467565b61047a8383610f26565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610467565b6103908286868403610826565b60003361036d818585610ab1565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff83166108c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661096b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610aab5781811015610a9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b610aab8484848403610826565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610b54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff8216610bf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604090205481811015610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020526040808220858503905591851681529081208054849290610cf1908490611508565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d5791815260200190565b60405180910390a3610aab565b73ffffffffffffffffffffffffffffffffffffffff8216610de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060356000828254610df39190611508565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604081208054839290610e2d908490611508565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b5050565b600054610100900460ff16610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b610e818282611110565b73ffffffffffffffffffffffffffffffffffffffff8216610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603360205260409020548181101561107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604081208383039055603580548492906110bb908490611520565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109cd565b505050565b600054610100900460ff166111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b60366111b3838261157d565b50603761110b828261157d565b600060208083528351808285015260005b818110156111ed578581018301518582016040015282016111d1565b818111156111ff576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125757600080fd5b919050565b6000806040838503121561126f57600080fd5b61127883611233565b946020939093013593505050565b60008060006060848603121561129b57600080fd5b6112a484611233565b92506112b260208501611233565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261130257600080fd5b813567ffffffffffffffff8082111561131d5761131d6112c2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611363576113636112c2565b8160405283815286602085880101111561137c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113b457600080fd5b853567ffffffffffffffff808211156113cc57600080fd5b6113d889838a016112f1565b965060208801359150808211156113ee57600080fd5b506113fb888289016112f1565b945050604086013560ff8116811461141257600080fd5b925061142060608701611233565b949793965091946080013592915050565b60006020828403121561144357600080fd5b61144c82611233565b9392505050565b6000806040838503121561146657600080fd5b61146f83611233565b915061147d60208401611233565b90509250929050565b600181811c9082168061149a57607f821691505b6020821081036114d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561151b5761151b6114d9565b500190565b600082821015611532576115326114d9565b500390565b601f82111561110b57600081815260208120601f850160051c8101602086101561155e5750805b601f850160051c820191505b818110156106865782815560010161156a565b815167ffffffffffffffff811115611597576115976112c2565b6115ab816115a58454611486565b84611537565b602080601f8311600181146115fe57600084156115c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610686565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561164b5788860151825594840194600190910190840161162c565b508582101561168757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220dbe4ae42463287341e0a5f486d0158c3cfe64d0921e8610c4a99cd4b5787807264736f6c634300080f0033a2646970667358221220f3d36271f729414602eb75fce97fce3c572e0ba1fc2f9e47c28ca6783d60b46764736f6c634300080f0033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/globalexitrootmanager.bin b/etherman/smartcontracts/bin/globalexitrootmanager.bin deleted file mode 100644 index 6ea7f47dad..0000000000 --- a/etherman/smartcontracts/bin/globalexitrootmanager.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b5061066c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c806333d6247d11610076578063485cc9551161005b578063485cc955146101445780635ec6a8df14610157578063a3c573eb1461019c57600080fd5b806333d6247d146100f65780633ed691ef1461010b57600080fd5b806301fd9044146100a8578063029f2793146100c4578063257b3632146100cd578063319cf735146100ed575b600080fd5b6100b160015481565b6040519081526020015b60405180910390f35b6100b160045481565b6100b16100db366004610562565b60036020526000908152604090205481565b6100b160025481565b610109610104366004610562565b6101bc565b005b6100b160025460015460408051602081019390935282015260009060600160405160208183030381529060405280519060200120905090565b6101096101523660046105a4565b610381565b6006546101779073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bb565b6005546101779073ffffffffffffffffffffffffffffffffffffffff1681565b60065473ffffffffffffffffffffffffffffffffffffffff163314806101f9575060055473ffffffffffffffffffffffffffffffffffffffff1633145b61028a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f476c6f62616c45786974526f6f744d616e616765723a3a75706461746545786960448201527f74526f6f743a204f4e4c595f414c4c4f5745445f434f4e54524143545300000060648201526084015b60405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff1633036102af5760018190555b60055473ffffffffffffffffffffffffffffffffffffffff1633036102d45760028190555b600480549060006102e4836105d7565b9091555050600254600154604080516020810193909352820152600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060045460008281526003909352928220839055600154600254919550939092917fb7c409af8cb511116b88f38824d48a0196194596241fdb2d177210d3d3b89fbf91a45050565b600054610100900460ff16158080156103a15750600054600160ff909116105b806103bb5750303b1580156103bb575060005460ff166001145b610447576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610281565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156104a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6006805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556005805492851692909116919091179055801561055d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006020828403121561057457600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461059f57600080fd5b919050565b600080604083850312156105b757600080fd5b6105c08361057b565b91506105ce6020840161057b565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361062f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea2646970667358221220d9ccfdddba433da7a9a14980d28db4b102be77f8af6cb74001850e88e278061864736f6c634300080f0033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/mockverifier.bin b/etherman/smartcontracts/bin/mockverifier.bin index 40c7093b49..e7983b3f28 100644 --- a/etherman/smartcontracts/bin/mockverifier.bin +++ b/etherman/smartcontracts/bin/mockverifier.bin @@ -1 +1 @@ -608060405234801561001057600080fd5b50610101806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806343753b4d14602d575b600080fd5b60426038366004606c565b6001949350505050565b604051901515815260200160405180910390f35b8060408101831015606657600080fd5b92915050565b600080600080610120808688031215608357600080fd5b608b87876056565b945060c0860187811115609d57600080fd5b60408701945060ab88826056565b93505086818701111560bc57600080fd5b5092959194509261010001915056fea2646970667358221220569286c06a35bb3b6e29da343de6015d1fc7ba685f6b59f888f00e18129e37df64736f6c634300080f0033 \ No newline at end of file +608060405234801561001057600080fd5b50610205806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80638d8f8a5c14610030575b600080fd5b61004661003e366004610128565b600192915050565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156100b2576100b261005a565b604052919050565b600082601f8301126100cb57600080fd5b604051602080820182811067ffffffffffffffff821117156100ef576100ef61005a565b604052818482018681111561010357600080fd5b855b8181101561011c5780358352918301918301610105565b50929695505050505050565b6000806040838503121561013b57600080fd5b823567ffffffffffffffff8082111561015357600080fd5b818501915085601f83011261016757600080fd5b813560208282111561017b5761017b61005a565b61018d601f8301601f19168201610089565b925081835287818386010111156101a357600080fd5b818185018285013760008183850101528295506101c2888289016100ba565b945050505050925092905056fea26469706673582212204af7f3bda67f3a30e1891af134e290590c6063b5a163b85e57b0c1111e1463a364736f6c63430008110033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/polygonzkevm.bin b/etherman/smartcontracts/bin/polygonzkevm.bin new file mode 100644 index 0000000000..5e5425e7d2 --- /dev/null +++ b/etherman/smartcontracts/bin/polygonzkevm.bin @@ -0,0 +1 @@ +6101406040523480156200001257600080fd5b5060405162004f5038038062004f508339810160408190526200003591620000a5565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b0391821661010052166101205262000131565b6001600160a01b03811681146200008557600080fd5b50565b80516001600160401b0381168114620000a057600080fd5b919050565b60008060008060008060c08789031215620000bf57600080fd5b8651620000cc816200006f565b6020880151909650620000df816200006f565b6040880151909550620000f2816200006f565b606088015190945062000105816200006f565b9250620001156080880162000088565b91506200012560a0880162000088565b90509295509295509295565b60805160a05160c05160e0516101005161012051614d51620001ff6000396000818161063801528181610d3201526126ef01526000818161077b0152610d0801526000818161072e0152818161192301528181612baf015261356f0152600081816108b9015281816111eb015281816115f3015281816120fa01528181612cd401528181612eb001526136e60152600081816109550152818161347601526139ac015260008181610830015281816118f101528181611d9301528181612e840152613a740152614d516000f3fe608060405234801561001057600080fd5b50600436106103ba5760003560e01c80638c3d7301116101f4578063c89e42df1161011a578063e7a7ed02116100ad578063f14916d61161007c578063f14916d61461099e578063f2fde38b146109b1578063f851a440146109c4578063f8b823e4146109d757600080fd5b8063e7a7ed0214610936578063e8bf92ed14610950578063eaeb077b14610977578063ed6b01041461098a57600080fd5b8063d8d1091b116100e9578063d8d1091b146108ee578063d939b31514610901578063dbc169761461091b578063e6ad707e1461092357600080fd5b8063c89e42df14610887578063cfa8ed471461089a578063d02103ca146108b4578063d2e129f9146108db57600080fd5b8063ada8f91911610192578063b6b0b09711610161578063b6b0b0971461082b578063ba58ae3914610852578063c0ed84e014610865578063c754c7ed1461086d57600080fd5b8063ada8f91914610763578063adc879e914610776578063afd23cbe1461079d578063b4d63f58146107cb57600080fd5b80639c9f3dfe116101ce5780639c9f3dfe14610703578063a066215c14610716578063a3c573eb14610729578063a50a164b1461075057600080fd5b80638c3d7301146106e25780638da5cb5b146106ea57806399f5634e146106fb57600080fd5b80634a910e6a116102e45780636b8616ce116102775780637fcb3653116102465780637fcb365314610620578063831c7ead14610633578063837a47381461065a578063841b24d7146106c857600080fd5b80636b8616ce146105d25780636ff512cc146105f2578063715018a6146106055780637215541a1461060d57600080fd5b8063542028d5116102b3578063542028d5146105a75780635e9145c9146105af5780635ec91958146105c257806360469169146105ca57600080fd5b80634a910e6a146105405780634e487706146105535780634fd70464146105665780635392c5e01461057957600080fd5b8063267822471161035c578063423fa8561161032b578063423fa856146104df57806345605267146104f9578063458c0477146105135780634a1a89a71461052657600080fd5b80632678224714610474578063298789831461049f578063383b3be8146104b9578063394218e9146104cc57600080fd5b806315064c961161039857806315064c961461041e5780631816b7e51461043b57806319d8ac611461044e578063220d78991461046157600080fd5b80630808270c146103bf5780630a0d9fbe146103d4578063107bf28c14610409575b600080fd5b6103d26103cd366004614303565b6109e0565b005b606f546103ec9061010090046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b610411610a79565b60405161040091906143eb565b606f5461042b9060ff1681565b6040519015158152602001610400565b6103d26104493660046143fe565b610b07565b6073546103ec906001600160401b031681565b61041161046f366004614422565b610be5565b607b54610487906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b60745461048790600160401b90046001600160a01b031681565b61042b6104c736600461446f565b610d90565b6103d26104da36600461446f565b610dd7565b6073546103ec90600160401b90046001600160401b031681565b6073546103ec90600160801b90046001600160401b031681565b6079546103ec906001600160401b031681565b6079546103ec90600160401b90046001600160401b031681565b6103d261054e36600461446f565b610eef565b6103d261056136600461446f565b610f77565b6103d261057436600461448a565b61107e565b61059961058736600461446f565b60756020526000908152604090205481565b604051908152602001610400565b610411611358565b6103d26105bd36600461456d565b611365565b6103d26119d4565b610599611a95565b6105996105e036600461446f565b60716020526000908152604090205481565b6103d26106003660046145c0565b611aab565b6103d2611b45565b6103d261061b36600461446f565b611b59565b6074546103ec906001600160401b031681565b6103ec7f000000000000000000000000000000000000000000000000000000000000000081565b61069d6106683660046145db565b6078602052600090815260409020805460018201546002909201546001600160401b0380831693600160401b90930416919084565b604080516001600160401b039586168152949093166020850152918301526060820152608001610400565b6079546103ec90600160c01b90046001600160401b031681565b6103d2611cb1565b6033546001600160a01b0316610487565b610599611d58565b6103d261071136600461446f565b611e7b565b6103d261072436600461446f565b611f87565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d261075e36600461448a565b61204f565b6103d26107713660046145c0565b61219b565b6103ec7f000000000000000000000000000000000000000000000000000000000000000081565b606f546107b8906901000000000000000000900461ffff1681565b60405161ffff9091168152602001610400565b6108066107d936600461446f565b607260205260009081526040902080546001909101546001600160401b0380821691600160401b90041683565b604080519384526001600160401b039283166020850152911690820152606001610400565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b61042b6108603660046145db565b612221565b6103ec6122a8565b607b546103ec90600160a01b90046001600160401b031681565b6103d2610895366004614696565b6122f5565b606f5461048790600160581b90046001600160a01b031681565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d26108e93660046146d2565b61235c565b6103d26108fc366004614784565b612777565b6079546103ec90600160801b90046001600160401b031681565b6103d2612b82565b6103d2610931366004614303565b612c28565b6073546103ec90600160c01b90046001600160401b031681565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d26109853660046147c5565b612dbf565b607b5461042b90600160e01b900460ff1681565b6103d26109ac3660046145c0565b6130bb565b6103d26109bf3660046145c0565b613155565b607a54610487906001600160a01b031681565b61059960705481565b606f5460ff1615610a0457604051630bc011ff60e21b815260040160405180910390fd5b610a1488888888888888886131e2565b6001600160401b0385166000908152607560209081526040918290205482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a1610a6f61356d565b5050505050505050565b60778054610a8690614810565b80601f0160208091040260200160405190810160405280929190818152602001828054610ab290614810565b8015610aff5780601f10610ad457610100808354040283529160200191610aff565b820191906000526020600020905b815481529060010190602001808311610ae257829003601f168201915b505050505081565b607a546001600160a01b03163314610b3257604051634755657960e01b815260040160405180910390fd5b6103e88161ffff161080610b4b57506103ff8161ffff16115b15610b82576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80546affff0000000000000000001916690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b6001600160401b038086166000818152607260205260408082205493881682529020546060929115801590610c18575081155b15610c4f576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610c86576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8f84612221565b610cc5576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516bffffffffffffffffffffffff193360601b166020820152603481019690965260548601929092526001600160c01b031960c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b6079546001600160401b0382811660009081526078602052604081205490924292610dc692600160801b90920481169116614860565b6001600160401b0316111592915050565b607a546001600160a01b03163314610e0257604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115610e2f57604051631d06e87960e01b815260040160405180910390fd5b606f5460ff16610e88576079546001600160401b03600160c01b909104811690821610610e88576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b6001600160401b038416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610bda565b607454600160401b90046001600160a01b03163314610f6b57606f5460ff1615610f2c57604051630bc011ff60e21b815260040160405180910390fd5b610f3581610d90565b610f6b576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f74816135e8565b50565b607a546001600160a01b03163314610fa257604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115610fcf5760405163f5e37f2f60e01b815260040160405180910390fd5b606f5460ff1661100f57607b546001600160401b03600160a01b90910481169082161061100f5760405163f5e37f2f60e01b815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b6001600160401b038416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610bda565b606f5460ff16156110a257604051630bc011ff60e21b815260040160405180910390fd5b6079546001600160401b0386811660009081526072602052604090206001015442926110d992600160c01b90910481169116614860565b6001600160401b0316111561111a576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86111278787614887565b6001600160401b0316111561114f57604051635acfba9d60e11b815260040160405180910390fd5b61115e878787878787876137a0565b61116785613a9b565b607954600160801b90046001600160401b0316600003611254576074805467ffffffffffffffff19166001600160401b03878116918217909255600090815260756020526040902084905560795416156111d557607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561123757600080fd5b505af115801561124b573d6000803e3d6000fd5b5050505061130e565b61125c613c70565b607980546001600160401b0316906000611275836148a7565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815288831660208083019182528284018a8152606084018a8152607954871660009081526078909352949091209251835492518616600160401b026fffffffffffffffffffffffffffffffff199093169516949094171781559151600183015551600290910155505b60405183815233906001600160401b038716907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966906020015b60405180910390a350505050505050565b60768054610a8690614810565b606f5460ff161561138957604051630bc011ff60e21b815260040160405180910390fd5b606f54600160581b90046001600160a01b031633146113d4576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160008190036113f75760405163cb591a5f60e01b815260040160405180910390fd5b6103e881111561141a57604051635acfba9d60e11b815260040160405180910390fd5b6073546001600160401b03600160401b82048116600081815260726020526040812054838516949293600160801b909304909216919082905b868110156117b15760008a8a8381811061146f5761146f6148cd565b905060200281019061148191906148e3565b61148a90614903565b805180516020909101206060820151919250906001600160401b0316156115b057856114b5816148a7565b965050600081836020015184606001516040516020016114f593929190928352602083019190915260c01b6001600160c01b031916604082015260480190565b60408051601f1981840301815291815281516020928301206001600160401b038a166000908152607190935291205490915081146115465760405163671ebaaf60e11b815260040160405180910390fd5b6001600160401b0380881660009081526071602052604080822091909155606085015190850151908216911610156115aa576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506116c7565b60208201511580159061166a575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063257b3632906024016020604051808303816000875af1158015611644573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611668919061498f565b155b156116a1576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156116c7576040516328a69b1f60e21b815260040160405180910390fd5b876001600160401b031682604001516001600160401b031610806116f757504282604001516001600160401b0316115b1561172e576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b6001600160c01b03191660808301528b901b6bffffffffffffffffffffffff19166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806117a9906149a8565b915050611453565b506117bc8685614860565b6073549094506001600160401b03600160c01b909104811690841611156117f65760405163c630a00d60e01b815260040160405180910390fd5b60006118028285614887565b611815906001600160401b0316886149c1565b60408051606081018252858152426001600160401b03908116602080840191825260738054600160401b9081900485168688019081528d861660008181526072909552979093209551865592516001909501805492519585166fffffffffffffffffffffffffffffffff199384161795851684029590951790945583548c84169116179302929092179055909150828116908516146118d4576073805467ffffffffffffffff60801b1916600160801b6001600160401b038716021790555b6119193330836070546118e791906149da565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016929190613d14565b611921613c70565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166379e2cf976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b50506040516001600160401b03881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce9150600090a250505050505050505050565b607a546001600160a01b031633146119ff57604051634755657960e01b815260040160405180910390fd5b607b54600160e01b900460ff16611a42576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f90600090a1565b60006070546064611aa691906149da565b905090565b607a546001600160a01b03163314611ad657604051634755657960e01b815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff16600160581b6001600160a01b038416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610bda565b611b4d613dcb565b611b576000613e25565b565b6033546001600160a01b03163314611ca9576000611b756122a8565b9050806001600160401b0316826001600160401b031611611bc2576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6073546001600160401b03600160401b90910481169083161180611c0157506001600160401b0380831660009081526072602052604090206001015416155b15611c38576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b038083166000908152607260205260409020600101544291611c669162093a809116614860565b6001600160401b03161115611ca7576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b610f7461356d565b607b546001600160a01b03163314611cf5576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfe919061498f565b90506000611e0a6122a8565b6073546001600160401b03600160401b8204811691611e3a91600160801b8204811691600160c01b900416614887565b611e449190614860565b611e4e9190614887565b6001600160401b0316905080600003611e6a5760009250505090565b611e748183614a07565b9250505090565b607a546001600160a01b03163314611ea657604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115611ed357604051630cc9650760e41b815260040160405180910390fd5b606f5460ff16611f2c576079546001600160401b03600160801b909104811690821610611f2c576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805467ffffffffffffffff60801b1916600160801b6001600160401b038416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610bda565b607a546001600160a01b03163314611fb257604051634755657960e01b815260040160405180910390fd5b62015180816001600160401b03161115611ff8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f805468ffffffffffffffff0019166101006001600160401b038416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610bda565b607454600160401b90046001600160a01b031633146120815760405163bbcbbc0560e01b815260040160405180910390fd5b612090878787878787876137a0565b6074805467ffffffffffffffff19166001600160401b03878116918217909255600090815260756020526040902084905560795416156120e457607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561214657600080fd5b505af115801561215a573d6000803e3d6000fd5b50506040518581523392506001600160401b03881691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe90602001611347565b607a546001600160a01b031633146121c657604051634755657960e01b815260040160405180910390fd5b607b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610bda565b600067ffffffff000000016001600160401b038316108015612257575067ffffffff00000001604083901c6001600160401b0316105b8015612277575067ffffffff00000001608083901c6001600160401b0316105b801561228e575067ffffffff0000000160c083901c105b1561229b57506001919050565b506000919050565b919050565b6079546000906001600160401b0316156122e557506079546001600160401b03908116600090815260786020526040902054600160401b90041690565b506074546001600160401b031690565b607a546001600160a01b0316331461232057604051634755657960e01b815260040160405180910390fd5b607661232c8282614a69565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610bda91906143eb565b600054610100900460ff161580801561237c5750600054600160ff909116105b806123965750303b158015612396575060005460ff166001145b61240d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015612430576000805461ff0019166101001790555b61243d60208801886145c0565b607a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905561247a60408801602089016145c0565b606f80546001600160a01b0392909216600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff9092169190911790556124ca60808801606089016145c0565b607480546001600160a01b0392909216600160401b027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790556000805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad86905560766125438682614a69565b5060776125508582614a69565b5062093a806125656060890160408a0161446f565b6001600160401b0316111561258d57604051630cc9650760e41b815260040160405180910390fd5b61259d606088016040890161446f565b607980546001600160401b0392909216600160801b0267ffffffffffffffff60801b1990921691909117905562093a806125dd60a0890160808a0161446f565b6001600160401b0316111561260557604051631d06e87960e01b815260040160405180910390fd5b61261560a088016080890161446f565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b6001600160401b03939093169290920291909117905567016345785d8a0000607055606f80546affffffffffffffffffff0019166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556126ca613e84565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd660007f000000000000000000000000000000000000000000000000000000000000000085856040516127209493929190614b51565b60405180910390a1801561276e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b607b54600160e01b900460ff16156127a2576040516324eff8c360e01b815260040160405180910390fd5b606f5460ff16156127c657604051630bc011ff60e21b815260040160405180910390fd5b8060008190036127e95760405163cb591a5f60e01b815260040160405180910390fd5b6103e881111561280c57604051635acfba9d60e11b815260040160405180910390fd5b6073546001600160401b03600160c01b8204811691612834918491600160801b900416614b88565b11156128535760405163c630a00d60e01b815260040160405180910390fd5b6073546001600160401b03600160401b820481166000818152607260205260408120549193600160801b9004909216915b84811015612a6c5760008787838181106128a0576128a06148cd565b90506020028101906128b29190614b9b565b6128bb90614bb1565b9050836128c7816148a7565b825180516020918201208185015160408087015190519499509194506000936129119386939101928352602083019190915260c01b6001600160c01b031916604082015260480190565b60408051601f1981840301815291815281516020928301206001600160401b0389166000908152607190935291205490915081146129625760405163671ebaaf60e11b815260040160405180910390fd5b6001600160401b0386166000908152607160205260408120556129866001896149c1565b84036129f35742607b60149054906101000a90046001600160401b031684604001516129b29190614860565b6001600160401b031611156129f3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b6001600160c01b031916608083015233901b6bffffffffffffffffffffffff19166088820152609c016040516020818303038152906040528051906020012094505050508080612a64906149a8565b915050612884565b50612a778484614860565b607380546001600160401b0342811667ffffffffffffffff199092168217808455604080516060810182528781526020808201958652600160401b9384900485168284019081528589166000818152607290935284832093518455965160019390930180549151871686026fffffffffffffffffffffffffffffffff1990921693871693909317179091558554938916600160801b0267ffffffffffffffff60801b19938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a546001600160a01b03163314612bad57604051634755657960e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dbc169766040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c0857600080fd5b505af1158015612c1c573d6000803e3d6000fd5b50505050611b57613f0a565b607454600160401b90046001600160a01b03163314612c5a5760405163bbcbbc0560e01b815260040160405180910390fd5b612c6a88888888888888886131e2565b6074805467ffffffffffffffff19166001600160401b0387811691821790925560009081526075602052604090208490556079541615612cbe57607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b158015612d2057600080fd5b505af1158015612d34573d6000803e3d6000fd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a80000000000000000000000000000000000000000000000000179055505060405183815233906001600160401b038716907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a35050505050505050565b607b54600160e01b900460ff1615612dea576040516324eff8c360e01b815260040160405180910390fd5b606f5460ff1615612e0e57604051630bc011ff60e21b815260040160405180910390fd5b6000612e18611a95565b905081811115612e54576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115612e77576040516328a69b1f60e21b815260040160405180910390fd5b612eac6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084613d14565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f30919061498f565b60738054919250600160c01b9091046001600160401b0316906018612f54836148a7565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508484604051612f89929190614c2c565b60408051918290038220602083015281018290526001600160c01b03194260c01b16606082015260680160408051808303601f190181529181528151602092830120607354600160c01b90046001600160401b03166000908152607190935291205532330361305757607354604080518381523360208201526060918101829052600091810191909152600160c01b9091046001600160401b0316907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26130b4565b607360189054906101000a90046001600160401b03166001600160401b03167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516130ab9493929190614c3c565b60405180910390a25b5050505050565b607a546001600160a01b031633146130e657604051634755657960e01b815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610bda565b61315d613dcb565b6001600160a01b0381166131d95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612404565b610f7481613e25565b60006001600160401b03891615613276576079546001600160401b03908116908a1611156132235760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038089166000908152607860205260409020600281015481549092898116600160401b909204161461327057604051632bd2e3e760e01b815260040160405180910390fd5b506132de565b506001600160401b038616600090815260756020526040902054806132ae576040516324cbdcc360e11b815260040160405180910390fd5b6074546001600160401b0390811690881611156132de57604051630f2b74f160e11b815260040160405180910390fd5b6079546001600160401b03908116908916118061330d5750886001600160401b0316886001600160401b031611155b8061332e57506079546001600160401b03600160401b909104811690891611155b15613365576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b03888116600090815260786020526040902054600160401b90048116908716146133c2576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006133d18888888589610be5565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516134069190614c65565b602060405180830381855afa158015613423573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613446919061498f565b6134509190614c77565b604080516020810182528281529051632363e29760e21b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916134ad9189918991600401614c8b565b602060405180830381865afa1580156134ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ee9190614cd3565b61350b576040516309bde33960e01b815260040160405180910390fd5b6001600160401b038a16600090815260786020526040902060020154869003613560576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156135c857600080fd5b505af11580156135dc573d6000803e3d6000fd5b50505050611b57613f7b565b6079546001600160401b03600160401b909104811690821611158061361b57506079546001600160401b03908116908216115b15613652576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b038181166000818152607860209081526040808320805460748054600160401b9283900490981667ffffffffffffffff1990981688179055600282015487865260759094529382902092909255607980546fffffffffffffffff000000000000000019169390940292909217909255600182015490516333d6247d60e01b815260048101919091529091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561373257600080fd5b505af1158015613746573d6000803e3d6000fd5b50505050826001600160401b0316816001600160401b03167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161379391815260200190565b60405180910390a3505050565b6000806137ab6122a8565b90506001600160401b03891615613841576079546001600160401b03908116908a1611156137ec5760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a1660009081526078602052604090206002810154815490945090918a8116600160401b909204161461383b57604051632bd2e3e760e01b815260040160405180910390fd5b506138ad565b6001600160401b03881660009081526075602052604090205491508161387a576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156138ad57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b0316116138f8576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613907898989868a610be5565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161393c9190614c65565b602060405180830381855afa158015613959573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061397c919061498f565b6139869190614c77565b604080516020810182528281529051632363e29760e21b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916139e3918a918a91600401614c8b565b602060405180830381865afa158015613a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a249190614cd3565b613a41576040516309bde33960e01b815260040160405180910390fd5b61356033613a4f858c614887565b6001600160401b0316613a60611d58565b613a6a91906149da565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190613fd7565b6000613aa56122a8565b905081600080613ab58484614887565b606f546001600160401b039182169250600091613ad891610100900416426149c1565b90505b846001600160401b0316846001600160401b031614613b59576001600160401b0380851660009081526072602052604090206001810154909116821015613b38576001810154600160401b90046001600160401b03169450613b53565b613b428686614887565b6001600160401b0316935050613b59565b50613adb565b6000613b6584846149c1565b905083811015613bbc57808403600c8111613b805780613b83565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281613bb257613bb26149f1565b0460705550613c2c565b838103600c8111613bcd5780613bd0565b600c5b90506000816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281613c0757613c076149f1565b04905080607054670de0b6b3a76400000281613c2557613c256149f1565b0460705550505b683635c9adc5dea000006070541115613c5157683635c9adc5dea0000060705561276e565b633b9aca00607054101561276e57633b9aca0060705550505050505050565b6079546001600160401b03600160401b8204811691161115611b5757607954600090613cad90600160401b90046001600160401b03166001614860565b9050613cb881610d90565b15610f7457607954600090600290613cda9084906001600160401b0316614887565b613ce49190614cf5565b613cee9083614860565b9050613cf981610d90565b15613d0b57613d07816135e8565b5050565b613d07826135e8565b6040516001600160a01b0380851660248301528316604482015260648101829052613dc59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614025565b50505050565b6033546001600160a01b03163314611b575760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612404565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16613f015760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612404565b611b5733613e25565b606f5460ff16613f46576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b606f5460ff1615613f9f57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b6040516001600160a01b0383166024820152604481018290526140209084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401613d61565b505050565b600061407a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661410a9092919063ffffffff16565b80519091501561402057808060200190518101906140989190614cd3565b6140205760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612404565b60606141198484600085614123565b90505b9392505050565b60608247101561419b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612404565b6001600160a01b0385163b6141f25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612404565b600080866001600160a01b0316858760405161420e9190614c65565b60006040518083038185875af1925050503d806000811461424b576040519150601f19603f3d011682016040523d82523d6000602084013e614250565b606091505b509150915061426082828661426b565b979650505050505050565b6060831561427a57508161411c565b82511561428a5782518084602001fd5b8160405162461bcd60e51b815260040161240491906143eb565b80356001600160401b03811681146122a357600080fd5b60008083601f8401126142cd57600080fd5b5081356001600160401b038111156142e457600080fd5b6020830191508360208285010111156142fc57600080fd5b9250929050565b60008060008060008060008060e0898b03121561431f57600080fd5b614328896142a4565b975061433660208a016142a4565b965061434460408a016142a4565b955061435260608a016142a4565b94506080890135935060a0890135925060c08901356001600160401b0381111561437b57600080fd5b6143878b828c016142bb565b999c989b5096995094979396929594505050565b60005b838110156143b657818101518382015260200161439e565b50506000910152565b600081518084526143d781602086016020860161439b565b601f01601f19169290920160200192915050565b60208152600061411c60208301846143bf565b60006020828403121561441057600080fd5b813561ffff8116811461411c57600080fd5b600080600080600060a0868803121561443a57600080fd5b614443866142a4565b9450614451602087016142a4565b94979496505050506040830135926060810135926080909101359150565b60006020828403121561448157600080fd5b61411c826142a4565b600080600080600080600060c0888a0312156144a557600080fd5b6144ae886142a4565b96506144bc602089016142a4565b95506144ca604089016142a4565b9450606088013593506080880135925060a08801356001600160401b038111156144f357600080fd5b6144ff8a828b016142bb565b989b979a50959850939692959293505050565b60008083601f84011261452457600080fd5b5081356001600160401b0381111561453b57600080fd5b6020830191508360208260051b85010111156142fc57600080fd5b80356001600160a01b03811681146122a357600080fd5b60008060006040848603121561458257600080fd5b83356001600160401b0381111561459857600080fd5b6145a486828701614512565b90945092506145b7905060208501614556565b90509250925092565b6000602082840312156145d257600080fd5b61411c82614556565b6000602082840312156145ed57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261461b57600080fd5b81356001600160401b0380821115614635576146356145f4565b604051601f8301601f19908116603f0116810190828211818310171561465d5761465d6145f4565b8160405283815286602085880101111561467657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156146a857600080fd5b81356001600160401b038111156146be57600080fd5b6146ca8482850161460a565b949350505050565b6000806000806000808688036101208112156146ed57600080fd5b60a08112156146fb57600080fd5b5086955060a0870135945060c08701356001600160401b038082111561472057600080fd5b61472c8a838b0161460a565b955060e089013591508082111561474257600080fd5b61474e8a838b0161460a565b945061010089013591508082111561476557600080fd5b5061477289828a016142bb565b979a9699509497509295939492505050565b6000806020838503121561479757600080fd5b82356001600160401b038111156147ad57600080fd5b6147b985828601614512565b90969095509350505050565b6000806000604084860312156147da57600080fd5b83356001600160401b038111156147f057600080fd5b6147fc868287016142bb565b909790965060209590950135949350505050565b600181811c9082168061482457607f821691505b60208210810361484457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156148805761488061484a565b5092915050565b6001600160401b038281168282160390808211156148805761488061484a565b60006001600160401b038083168181036148c3576148c361484a565b6001019392505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e198336030181126148f957600080fd5b9190910192915050565b60006080823603121561491557600080fd5b604051608081016001600160401b038282108183111715614938576149386145f4565b81604052843591508082111561494d57600080fd5b5061495a3682860161460a565b82525060208301356020820152614973604084016142a4565b6040820152614984606084016142a4565b606082015292915050565b6000602082840312156149a157600080fd5b5051919050565b6000600182016149ba576149ba61484a565b5060010190565b818103818111156149d4576149d461484a565b92915050565b80820281158282048414176149d4576149d461484a565b634e487b7160e01b600052601260045260246000fd5b600082614a1657614a166149f1565b500490565b601f82111561402057600081815260208120601f850160051c81016020861015614a425750805b601f850160051c820191505b81811015614a6157828155600101614a4e565b505050505050565b81516001600160401b03811115614a8257614a826145f4565b614a9681614a908454614810565b84614a1b565b602080601f831160018114614acb5760008415614ab35750858301515b600019600386901b1c1916600185901b178555614a61565b600085815260208120601f198616915b82811015614afa57888601518255948401946001909101908401614adb565b5085821015614b185787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160401b03808716835280861660208401525060606040830152614b7e606083018486614b28565b9695505050505050565b808201808211156149d4576149d461484a565b60008235605e198336030181126148f957600080fd5b600060608236031215614bc357600080fd5b604051606081016001600160401b038282108183111715614be657614be66145f4565b816040528435915080821115614bfb57600080fd5b50614c083682860161460a565b82525060208301356020820152614c21604084016142a4565b604082015292915050565b8183823760009101908152919050565b8481526001600160a01b0384166020820152606060408201526000614b7e606083018486614b28565b600082516148f981846020870161439b565b600082614c8657614c866149f1565b500690565b604081526000614c9f604083018587614b28565b905060208083018460005b6001811015614cc757815183529183019190830190600101614caa565b50505050949350505050565b600060208284031215614ce557600080fd5b8151801515811461411c57600080fd5b60006001600160401b0380841680614d0f57614d0f6149f1565b9216919091049291505056fea26469706673582212200b586a4d2a78f3585b9b741ea1f06c0afab4d66b48c408bc1e7be9fa34df798364736f6c63430008110033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/polygonzkevmbridge.bin b/etherman/smartcontracts/bin/polygonzkevmbridge.bin new file mode 100644 index 0000000000..dfd72577c1 --- /dev/null +++ b/etherman/smartcontracts/bin/polygonzkevmbridge.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50614e0e806100206000396000f3fe6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000506578063ee25560b146200051e578063fb570834146200054f57600080fd5b8063be5831c7146200049e578063cd58657914620004c4578063d02103ca14620004db57600080fd5b80639e34070f11620000be5780639e34070f14620003fa578063aaa13cc2146200043f578063bab161bf146200046457600080fd5b8063647c576c146200038357806379e2cf9714620003a857806381b1c17414620003c057600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf214620003245780633ae0504714620003465780633e197043146200035e57600080fd5b80632d2c9d9414620002695780632dfdf0b5146200028e578063318aee3d14620002b557600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200022d5780632cffd02e146200024457600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed62000574565b005b348015620001fc57600080fd5b50620002146200020e36600462002938565b620005ac565b6040516001600160a01b039091168152602001620001cc565b620001ed6200023e366004620029cf565b62000617565b3480156200025157600080fd5b50620001ed6200026336600462002a66565b6200073e565b3480156200027657600080fd5b50620001ed6200028836600462002a66565b62000b98565b3480156200029b57600080fd5b50620002a660535481565b604051908152602001620001cc565b348015620002c257600080fd5b50620002ff620002d436600462002b4c565b606b6020526000908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201620001cc565b3480156200033157600080fd5b50606c5462000214906001600160a01b031681565b3480156200035357600080fd5b50620002a662000d36565b3480156200036b57600080fd5b50620002a66200037d36600462002b7c565b62000e1c565b3480156200039057600080fd5b50620001ed620003a236600462002c06565b62000ec6565b348015620003b557600080fd5b50620001ed62001096565b348015620003cd57600080fd5b5062000214620003df36600462002c56565b606a602052600090815260409020546001600160a01b031681565b3480156200040757600080fd5b50620001c06200041936600462002c56565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200044c57600080fd5b50620002146200045e36600462002c70565b620010ba565b3480156200047157600080fd5b506068546200048890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620004ab57600080fd5b506068546200048890600160c81b900463ffffffff1681565b620001ed620004d536600462002d24565b6200120e565b348015620004e857600080fd5b5060685462000214906501000000000090046001600160a01b031681565b3480156200051357600080fd5b50620001ed620015f1565b3480156200052b57600080fd5b50620002a66200053d36600462002c56565b60696020526000908152604090205481565b3480156200055c57600080fd5b50620001c06200056e36600462002dc6565b62001627565b606c546001600160a01b03163314620005a05760405163e2e8106b60e01b815260040160405180910390fd5b620005aa6200170e565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091206000908152606a90915220546001600160a01b03165b92915050565b60685460ff16156200063c57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff868116610100909204161480620006625750600263ffffffff861610155b1562000681576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620006d79998979695949392919062002e3c565b60405180910390a162000726620007206001606860019054906101000a900463ffffffff163389893489896040516200071292919062002eaa565b604051809103902062000e1c565b6200176b565b821562000737576200073762001882565b5050505050565b60685460ff16156200076357604051630bc011ff60e21b815260040160405180910390fd5b6200077a8b8b8b8b8b8b8b8b8b8b8b600062001934565b6001600160a01b0386166200083c57604080516000808252602082019092526001600160a01b038616908590604051620007b5919062002ef6565b60006040518083038185875af1925050503d8060008114620007f4576040519150601f19603f3d011682016040523d82523d6000602084013e620007f9565b606091505b505090508062000835576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000b2d565b60685463ffffffff61010090910481169088160362000871576200086b6001600160a01b038716858562001aff565b62000b2d565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152606a9093529120549091506001600160a01b03168062000ac55760008080620008f08688018862002fcf565b9250925092506000858484846040516200090a90620028fc565b620009189392919062003073565b8190604051809103906000f590508015801562000939573d6000803e3d6000fd5b506040516340c10f1960e01b81526001600160a01b038c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b1580156200098957600080fd5b505af11580156200099e573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808e63ffffffff1681526020018d6001600160a01b0316815250606b6000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000ab3959493929190620030b0565b60405180910390a15050505062000b2a565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000b1057600080fd5b505af115801562000b25573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c81168252891660208201526001600160a01b0388811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000bbd57604051630bc011ff60e21b815260040160405180910390fd5b62000bd48b8b8b8b8b8b8b8b8b8b8b600162001934565b6000846001600160a01b031684888a868660405160240162000bfa9493929190620030eb565b60408051601f198184030181529181526020820180516001600160e01b03167f1806b5f2000000000000000000000000000000000000000000000000000000001790525162000c4a919062002ef6565b60006040518083038185875af1925050503d806000811462000c89576040519150601f19603f3d011682016040523d82523d6000602084013e62000c8e565b606091505b505090508062000cca576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562000e13578083901c60011660010362000da4576033816020811062000d705762000d7062003126565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062000dd1565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b6040805160208101849052908101839052606001604051602081830303815290604052805190602001209150808062000e0a9062003152565b91505062000d41565b50919392505050565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b600054610100900460ff161580801562000ee75750600054600160ff909116105b8062000f035750303b15801562000f03575060005460ff166001145b62000f7b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff19166001179055801562000f9f576000805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556200104962001b7d565b801562001090576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854600160c81b900463ffffffff161015620005aa57620005aa62001882565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200112590620028fc565b601f1982820381018352601f90910116604081905262001152908d908d908d908d908d906020016200316e565b60408051601f1981840301815290829052620011729291602001620031af565b60405160208183030381529060405280519060200120604051602001620011e894939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f1901815291905280516020909101209a9950505050505050505050565b60685460ff16156200123357604051630bc011ff60e21b815260040160405180910390fd5b6200123d62001bf4565b60685463ffffffff888116610100909204161480620012635750600263ffffffff881610155b1562001282576040516302caf51760e11b815260040160405180910390fd5b6000806060876001600160a01b038816620012db57883414620012d1576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001562565b341562001314576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038089166000908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620013ea576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b90526001600160a01b038a1690639dc29fac90604401600060405180830381600087803b158015620013bd57600080fd5b505af1158015620013d2573d6000803e3d6000fd5b50505050806020015194508060000151935062001560565b8515620013ff57620013ff898b898962001c4f565b6040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa15801562001447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200146d9190620031e2565b9050620014866001600160a01b038b1633308e62002015565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015620014ce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620014f49190620031e2565b9050620015028282620031fc565b6068548c9850610100900463ffffffff1696509350620015228762002068565b6200152d8c62002166565b620015388d62002251565b6040516020016200154c9392919062003073565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e8688605354604051620015a498979695949392919062003212565b60405180910390a1620015c962000720600085878f8f87898051906020012062000e1c565b8615620015da57620015da62001882565b50505050620015e860018055565b50505050505050565b606c546001600160a01b031633146200161d5760405163e2e8106b60e01b815260040160405180910390fd5b620005aa62002331565b600084815b60208110156200170257600163ffffffff8616821c811690036200169e578581602081106200165f576200165f62003126565b60200201358260405160200162001680929190918252602082015260400190565b604051602081830303815290604052805190602001209150620016ed565b81868260208110620016b457620016b462003126565b6020020135604051602001620016d4929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80620016f98162003152565b9150506200162c565b50909114949350505050565b60685460ff16156200173357604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b8060016200177c602060026200337b565b620017889190620031fc565b60535410620017c3576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000605360008154620017d69062003152565b9182905550905060005b602081101562001872578082901c6001166001036200181857826033826020811062001810576200181062003126565b015550505050565b603381602081106200182e576200182e62003126565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080620018699062003152565b915050620017e0565b506200187d62003389565b505050565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d620018e562000d36565b6040518263ffffffff1660e01b81526004016200190491815260200190565b600060405180830381600087803b1580156200191f57600080fd5b505af115801562001090573d6000803e3d6000fd5b620019458b63ffffffff16620023a3565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091526000916501000000000090046001600160a01b03169063257b3632906084016020604051808303816000875af1158015620019db573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a019190620031e2565b90508060000362001a3d576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001a6e576040516302caf51760e11b815260040160405180910390fd5b606854600090610100900463ffffffff1662001a8c57508962001a8f565b508a5b62001ab862001aaf848c8c8c8c8c8c8c6040516200071292919062002eaa565b8f8f8462001627565b62001aef576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b6040516001600160a01b0383166024820152604481018290526200187d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262002408565b600054610100900460ff1662001bea5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000f72565b620005aa620024f4565b60026001540362001c485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000f72565b6002600155565b600062001c6060048284866200339f565b62001c6b91620033cb565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b031982160162001e5757600080808080808062001cb6896004818d6200339f565b81019062001cc59190620033fc565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161462001d065760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301462001d305760405163750643af60e01b815260040160405180910390fd5b8a851462001d6a576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162001e03919062002ef6565b6000604051808303816000865af19150503d806000811462001e42576040519150601f19603f3d011682016040523d82523d6000602084013e62001e47565b606091505b5050505050505050505062000737565b6001600160e01b031981166323f2ebc360e21b1462001ea2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808080808062001eba8a6004818e6200339f565b81019062001ec9919062003457565b97509750975097509750975097509750336001600160a01b0316886001600160a01b03161462001f0c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301462001f365760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169162001fbf919062002ef6565b6000604051808303816000865af19150503d806000811462001ffe576040519150601f19603f3d011682016040523d82523d6000602084013e62002003565b606091505b50505050505050505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620010909085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162001b45565b60408051600481526024810182526020810180516001600160e01b03167f06fdde0300000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b03861691620020ca919062002ef6565b600060405180830381855afa9150503d806000811462002107576040519150601f19603f3d011682016040523d82523d6000602084013e6200210c565b606091505b50915091508162002153576040518060400160405280600781526020017f4e4f5f4e414d45000000000000000000000000000000000000000000000000008152506200215e565b6200215e8162002561565b949350505050565b60408051600481526024810182526020810180516001600160e01b03167f95d89b4100000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b03861691620021c8919062002ef6565b600060405180830381855afa9150503d806000811462002205576040519150601f19603f3d011682016040523d82523d6000602084013e6200220a565b606091505b50915091508162002153576040518060400160405280600981526020017f4e4f5f53594d424f4c00000000000000000000000000000000000000000000008152506200215e565b60408051600481526024810182526020810180516001600160e01b03167f313ce567000000000000000000000000000000000000000000000000000000001790529051600091829182916001600160a01b03861691620022b2919062002ef6565b600060405180830381855afa9150503d8060008114620022ef576040519150601f19603f3d011682016040523d82523d6000602084013e620022f4565b606091505b509150915081801562002308575080516020145b620023155760126200215e565b808060200190518101906200215e9190620034e3565b60018055565b60685460ff166200236e576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000737576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006200245f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620027519092919063ffffffff16565b8051909150156200187d578080602001905181019062002480919062003503565b6200187d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000f72565b600054610100900460ff166200232b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000f72565b6060604082511062002583578180602001905181019062000611919062003523565b8151602003620027135760005b602081108015620025db5750828181518110620025b157620025b162003126565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620025f65780620025ed8162003152565b91505062002590565b806000036200263a57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562002658576200265862002eba565b6040519080825280601f01601f19166020018201604052801562002683576020820181803683370190505b50905060005b828110156200270b57848181518110620026a757620026a762003126565b602001015160f81c60f81b828281518110620026c757620026c762003126565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620027028162003152565b91505062002689565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60606200276284846000856200276c565b90505b9392505050565b606082471015620027e65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000f72565b6001600160a01b0385163b6200283f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000f72565b600080866001600160a01b031685876040516200285d919062002ef6565b60006040518083038185875af1925050503d80600081146200289c576040519150601f19603f3d011682016040523d82523d6000602084013e620028a1565b606091505b5091509150620028b3828286620028be565b979650505050505050565b60608315620028cf57508162002765565b825115620028e05782518084602001fd5b8160405162461bcd60e51b815260040162000f729190620035a3565b61182080620035b983390190565b803563ffffffff811681146200274c57600080fd5b6001600160a01b03811681146200293557600080fd5b50565b600080604083850312156200294c57600080fd5b62002957836200290a565b9150602083013562002969816200291f565b809150509250929050565b80151581146200293557600080fd5b60008083601f8401126200299657600080fd5b50813567ffffffffffffffff811115620029af57600080fd5b602083019150836020828501011115620029c857600080fd5b9250929050565b600080600080600060808688031215620029e857600080fd5b620029f3866200290a565b9450602086013562002a05816200291f565b9350604086013562002a178162002974565b9250606086013567ffffffffffffffff81111562002a3457600080fd5b62002a428882890162002983565b969995985093965092949392505050565b8061040081018310156200061157600080fd5b60008060008060008060008060008060006105208c8e03121562002a8957600080fd5b62002a958d8d62002a53565b9a5062002aa66104008d016200290a565b99506104208c013598506104408c0135975062002ac76104608d016200290a565b96506104808c013562002ada816200291f565b955062002aeb6104a08d016200290a565b94506104c08c013562002afe816200291f565b93506104e08c013592506105008c013567ffffffffffffffff81111562002b2457600080fd5b62002b328e828f0162002983565b915080935050809150509295989b509295989b9093969950565b60006020828403121562002b5f57600080fd5b813562002765816200291f565b60ff811681146200293557600080fd5b600080600080600080600060e0888a03121562002b9857600080fd5b873562002ba58162002b6c565b965062002bb5602089016200290a565b9550604088013562002bc7816200291f565b945062002bd7606089016200290a565b9350608088013562002be9816200291f565b9699959850939692959460a0840135945060c09093013592915050565b60008060006060848603121562002c1c57600080fd5b62002c27846200290a565b9250602084013562002c39816200291f565b9150604084013562002c4b816200291f565b809150509250925092565b60006020828403121562002c6957600080fd5b5035919050565b600080600080600080600060a0888a03121562002c8c57600080fd5b62002c97886200290a565b9650602088013562002ca9816200291f565b9550604088013567ffffffffffffffff8082111562002cc757600080fd5b62002cd58b838c0162002983565b909750955060608a013591508082111562002cef57600080fd5b5062002cfe8a828b0162002983565b909450925050608088013562002d148162002b6c565b8091505092959891949750929550565b600080600080600080600060c0888a03121562002d4057600080fd5b62002d4b886200290a565b9650602088013562002d5d816200291f565b955060408801359450606088013562002d76816200291f565b9350608088013562002d888162002974565b925060a088013567ffffffffffffffff81111562002da557600080fd5b62002db38a828b0162002983565b989b979a50959850939692959293505050565b600080600080610460858703121562002dde57600080fd5b8435935062002df1866020870162002a53565b925062002e0261042086016200290a565b939692955092936104400135925050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600061010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015262002e90828501878962002e13565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562002eed57818101518382015260200162002ed3565b50506000910152565b6000825162002f0a81846020870162002ed0565b9190910192915050565b604051601f8201601f1916810167ffffffffffffffff8111828210171562002f405762002f4062002eba565b604052919050565b600067ffffffffffffffff82111562002f655762002f6562002eba565b50601f01601f191660200190565b600082601f83011262002f8557600080fd5b813562002f9c62002f968262002f48565b62002f14565b81815284602083860101111562002fb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562002fe557600080fd5b833567ffffffffffffffff8082111562002ffe57600080fd5b6200300c8783880162002f73565b945060208601359150808211156200302357600080fd5b50620030328682870162002f73565b925050604084013562002c4b8162002b6c565b600081518084526200305f81602086016020860162002ed0565b601f01601f19169290920160200192915050565b60608152600062003088606083018662003045565b82810360208401526200309c818662003045565b91505060ff83166040830152949350505050565b63ffffffff8616815260006001600160a01b03808716602084015280861660408401525060806060830152620028b360808301848662002e13565b6001600160a01b038516815263ffffffff841660208201526060604082015260006200311c60608301848662002e13565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016200316757620031676200313c565b5060010190565b6060815260006200318460608301878962002e13565b82810360208401526200319981868862002e13565b91505060ff831660408301529695505050505050565b60008351620031c381846020880162002ed0565b835190830190620031d981836020880162002ed0565b01949350505050565b600060208284031215620031f557600080fd5b5051919050565b818103818111156200061157620006116200313c565b600061010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620032658285018762003045565b925080851660e085015250509998505050505050505050565b600181815b80851115620032bf578160001904821115620032a357620032a36200313c565b80851615620032b157918102915b93841c939080029062003283565b509250929050565b600082620032d85750600162000611565b81620032e75750600062000611565b81600181146200330057600281146200330b576200332b565b600191505062000611565b60ff8411156200331f576200331f6200313c565b50506001821b62000611565b5060208310610133831016604e8410600b841016171562003350575081810a62000611565b6200335c83836200327e565b80600019048211156200337357620033736200313c565b029392505050565b6000620027658383620032c7565b634e487b7160e01b600052600160045260246000fd5b60008085851115620033b057600080fd5b83861115620033be57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015620033f45780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a0312156200341857600080fd5b873562003425816200291f565b9650602088013562003437816200291f565b95506040880135945060608801359350608088013562002be98162002b6c565b600080600080600080600080610100898b0312156200347557600080fd5b883562003482816200291f565b9750602089013562003494816200291f565b965060408901359550606089013594506080890135620034b48162002974565b935060a0890135620034c68162002b6c565b979a969950949793969295929450505060c08201359160e0013590565b600060208284031215620034f657600080fd5b8151620027658162002b6c565b6000602082840312156200351657600080fd5b8151620027658162002974565b6000602082840312156200353657600080fd5b815167ffffffffffffffff8111156200354e57600080fd5b8201601f810184136200356057600080fd5b80516200357162002f968262002f48565b8181528560208385010111156200358757600080fd5b6200359a82602083016020860162002ed0565b95945050505050565b6020815260006200276560208301846200304556fe6101006040523480156200001257600080fd5b50604051620018203803806200182083398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051611364620004bc60003960006102370152600081816102fa015281816105630152610623015260006104f701526000818161035f01526104c101526113646000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf14610381578063dd62ed3e14610394578063ffa1ad74146103cd57600080fd5b8063a457c2d714610334578063a9059cbb14610347578063cd0d00961461035a57600080fd5b806395d89b41116100bd57806395d89b41146102da5780639dc29fac146102e2578063a3c573eb146102f557600080fd5b806370a08231146102915780637ecebe00146102ba57600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ed565b6040516101919190611107565b60405180910390f35b6101ad6101a8366004611171565b61047f565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad61020436600461119b565b610499565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c16104bd565b6101ad610277366004611171565b610519565b61028f61028a366004611171565b610558565b005b6101c161029f3660046111d7565b6001600160a01b031660009081526020819052604090205490565b6101c16102c83660046111d7565b60056020526000908152604090205481565b610184610609565b61028f6102f0366004611171565b610618565b61031c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610191565b6101ad610342366004611171565b6106c0565b6101ad610355366004611171565b61076a565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f61038f3660046111f9565b610778565b6101c16103a236600461126c565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610184604051806040016040528060018152602001603160f81b81525081565b6060600380546103fc9061129f565b80601f01602080910402602001604051908101604052809291908181526020018280546104289061129f565b80156104755780601f1061044a57610100808354040283529160200191610475565b820191906000526020600020905b81548152906001019060200180831161045857829003601f168201915b5050505050905090565b60003361048d8185856109fd565b60019150505b92915050565b6000336104a7858285610b56565b6104b2858585610be8565b506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146104f4576104ef46610dff565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061048d90829086906105539087906112ef565b6109fd565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105fb5760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106058282610eab565b5050565b6060600480546103fc9061129f565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106b65760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084016105f2565b6106058282610f8a565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091908381101561075d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016105f2565b6104b282868684036109fd565b60003361048d818585610be8565b834211156107ed5760405162461bcd60e51b8152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d69740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661083a83611302565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006108986104bd565b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101919091526042810183905260620160408051601f198184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa15801561093e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906109745750896001600160a01b0316816001600160a01b0316145b6109e65760405162461bcd60e51b815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e61747572650000000000000000000000000000000000000000000000000060648201526084016105f2565b6109f18a8a8a6109fd565b50505050505050505050565b6001600160a01b038316610a785760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216610af45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610be25781811015610bd55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105f2565b610be284848484036109fd565b50505050565b6001600160a01b038316610c645760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216610ce05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03831660009081526020819052604090205481811015610d6f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610da69084906112ef565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610df291815260200190565b60405180910390a3610be2565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e2a6103ed565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6001600160a01b038216610f015760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f2565b8060026000828254610f1391906112ef565b90915550506001600160a01b03821660009081526020819052604081208054839290610f409084906112ef565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166110065760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216600090815260208190526040902054818110156110955760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03831660009081526020819052604081208383039055600280548492906110c490849061131b565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b49565b600060208083528351808285015260005b8181101561113457858101830151858201604001528201611118565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461116c57600080fd5b919050565b6000806040838503121561118457600080fd5b61118d83611155565b946020939093013593505050565b6000806000606084860312156111b057600080fd5b6111b984611155565b92506111c760208501611155565b9150604084013590509250925092565b6000602082840312156111e957600080fd5b6111f282611155565b9392505050565b600080600080600080600060e0888a03121561121457600080fd5b61121d88611155565b965061122b60208901611155565b95506040880135945060608801359350608088013560ff8116811461124f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561127f57600080fd5b61128883611155565b915061129660208401611155565b90509250929050565b600181811c908216806112b357607f821691505b6020821081036112d357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610493576104936112d9565b600060018201611314576113146112d9565b5060010190565b81810381811115610493576104936112d956fea264697066735822122096b785fb92e9d4372a52fbc641ca1490dd9eca1990f97279973ebfb2e360d35264736f6c63430008110033a26469706673582212203e56a8c8e90f8393064aa68599de6b13ecf8da3fea75bef5ecea9d2366baca9264736f6c63430008110033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/polygonzkevmglobalexitroot.bin b/etherman/smartcontracts/bin/polygonzkevmglobalexitroot.bin new file mode 100644 index 0000000000..466fe05c74 --- /dev/null +++ b/etherman/smartcontracts/bin/polygonzkevmglobalexitroot.bin @@ -0,0 +1 @@ +60c060405234801561001057600080fd5b506040516103f83803806103f883398101604081905261002f91610062565b6001600160a01b0391821660a05216608052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a0516103316100c76000396000818160e901526101bd015260008181610135015261017401526103316000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806333d6247d1161005b57806333d6247d146100c75780633ed691ef146100dc5780635ec6a8df146100e4578063a3c573eb1461013057600080fd5b806301fd904414610082578063257b36321461009e578063319cf735146100be575b600080fd5b61008b60005481565b6040519081526020015b60405180910390f35b61008b6100ac3660046102e2565b60026020526000908152604090205481565b61008b60015481565b6100da6100d53660046102e2565b610157565b005b61008b6102a6565b61010b7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610095565b61010b7f000000000000000000000000000000000000000000000000000000000000000081565b60005460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101a65750600182905581610222565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101f0576000839055829150610222565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602080820184905281830185905282518083038401815260609092019092528051910120600090600081815260026020526040812054919250036102a05760008181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b60006102dd600154600054604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b6000602082840312156102f457600080fd5b503591905056fea26469706673582212209f4342d0e9635341e8c77469d3bc7ae71f0dddc6e79aebfb62c8bb1ad4fe68d664736f6c63430008110033 \ No newline at end of file diff --git a/etherman/smartcontracts/bin/proofofefficiency.bin b/etherman/smartcontracts/bin/proofofefficiency.bin deleted file mode 100644 index d57c65ec17..0000000000 --- a/etherman/smartcontracts/bin/proofofefficiency.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561001057600080fd5b50614a6d806100206000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063ac2eba9811610104578063d02103ca116100a2578063e8bf92ed11610071578063e8bf92ed146104de578063eaeb077b146104fc578063f755276114610518578063f7d2cd7f14610536576101cf565b8063d02103ca14610468578063d2fd1b3114610486578063d8f54db0146104a2578063e7a7ed02146104c0576101cf565b8063b4d63f58116100de578063b4d63f58146103de578063b6b0b09714610410578063c89e42df1461042e578063cfa8ed471461044a576101cf565b8063ac2eba9814610384578063adc879e9146103a2578063b02286c0146103c0576101cf565b8063798470571161017157806395297e241161014b57806395297e2414610310578063959c2f471461032c578063aa0f44181461034a578063ab9fc5ef14610366576101cf565b806379847057146102b85780637fcb3653146102d65780638c4a0af7146102f4576101cf565b806345605267116101ad578063456052671461022e578063542028d51461024c5780636b8616ce1461026a5780636ff512cc1461029c576101cf565b8063107bf28c146101d457806319d8ac61146101f2578063423fa85614610210575b600080fd5b6101dc610552565b6040516101e991906127ea565b60405180910390f35b6101fa6105e0565b604051610207919061282f565b60405180910390f35b6102186105fa565b604051610225919061282f565b60405180910390f35b610236610614565b604051610243919061282f565b60405180910390f35b61025461062e565b60405161026191906127ea565b60405180910390f35b610284600480360381019061027f919061288a565b6106bc565b604051610293939291906128e9565b60405180910390f35b6102b660048036038101906102b1919061297e565b6106fa565b005b6102c0610805565b6040516102cd91906129ab565b60405180910390f35b6102de61086d565b6040516102eb919061282f565b60405180910390f35b61030e600480360381019061030991906129fe565b610887565b005b61032a60048036038101906103259190612aa0565b61096b565b005b610334610f96565b6040516103419190612b2f565b60405180910390f35b610364600480360381019061035f919061288a565b610f9c565b005b61036e6113ac565b60405161037b919061282f565b60405180910390f35b61038c6113b3565b6040516103999190612b2f565b60405180910390f35b6103aa6113b9565b6040516103b7919061282f565b60405180910390f35b6103c86113d3565b6040516103d591906129ab565b60405180910390f35b6103f860048036038101906103f3919061288a565b6113d9565b60405161040793929190612b4a565b60405180910390f35b61041861142b565b6040516104259190612be0565b60405180910390f35b61044860048036038101906104439190612d30565b611451565b005b61045261152b565b60405161045f9190612d88565b60405180910390f35b610470611551565b60405161047d9190612dc4565b60405180910390f35b6104a0600480360381019061049b9190612e99565b611577565b005b6104aa611824565b6040516104b79190612faa565b60405180910390f35b6104c8611837565b6040516104d5919061282f565b60405180910390f35b6104e6611851565b6040516104f39190612fe6565b60405180910390f35b610516600480360381019061051191906130ce565b611877565b005b610520611ca2565b60405161052d91906129ab565b60405180910390f35b610550600480360381019061054b9190613388565b611cae565b005b600b805461055f90613400565b80601f016020809104026020016040519081016040528092919081815260200182805461058b90613400565b80156105d85780601f106105ad576101008083540402835291602001916105d8565b820191906000526020600020905b8154815290600101906020018083116105bb57829003601f168201915b505050505081565b600360009054906101000a900467ffffffffffffffff1681565b600360089054906101000a900467ffffffffffffffff1681565b600360109054906101000a900467ffffffffffffffff1681565b6009805461063b90613400565b80601f016020809104026020016040519081016040528092919081815260200182805461066790613400565b80156106b45780601f10610689576101008083540402835291602001916106b4565b820191906000526020600020905b81548152906001019060200180831161069757829003601f168201915b505050505081565b60016020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900467ffffffffffffffff16905083565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461078a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610781906134a3565b60405180910390fd5b80600460086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0816040516107fa9190612d88565b60405180910390a150565b6000600360109054906101000a900467ffffffffffffffff16600360189054906101000a900467ffffffffffffffff16600161084191906134f2565b61084b9190613530565b67ffffffffffffffff16670de0b6b3a76400006108689190613564565b905090565b600460009054906101000a900467ffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610917576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090e906134a3565b60405180910390fd5b806004601c6101000a81548160ff0219169083151502179055507fbacda50a4a8575be1d91a7ebe29ee45056f3a94f12a2281eb6b43afa33bcefe6816040516109609190612faa565b60405180910390a150565b6001600460009054906101000a900467ffffffffffffffff1661098e91906134f2565b67ffffffffffffffff168467ffffffffffffffff16146109e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da90613630565b60405180910390fd5b600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff168467ffffffffffffffff161115610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a47906136e8565b60405180910390fd5b6000600260008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160009054906101000a900467ffffffffffffffff1690506000806000600260008967ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610b2357600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000154915067016345785d8a00009050610bed565b600060016000600260008b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152505090508060000151925080602001519150505b60006006546007548a8c868c89600a60009054906101000a900467ffffffffffffffff16604051602001610c2898979695949392919061375f565b604051602081830303815290604052805190602001209050606060405190506054604082010160405260548152602081013360601b815260148101905060005b6008811015610c905783602082021c60e01b60201c8252600882019150600181019050610c68565b505060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051610cc59190613838565b602060405180830381855afa158015610ce2573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610d059190613864565b60001c610d1291906138c0565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166343753b4d8a8a8a6040518060200160405280878152506040518563ffffffff1660e01b8152600401610d839493929190613a6b565b602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613ac7565b610e03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfa90613b66565b60405180910390fd5b6004600081819054906101000a900467ffffffffffffffff1680929190610e2990613b86565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508a6006819055508b600781905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333d6247d6007546040518263ffffffff1660e01b8152600401610ebb9190612b2f565b600060405180830381600087803b158015610ed557600080fd5b505af1158015610ee9573d6000803e3d6000fd5b50505050610f3a3385600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166123c59092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff168a67ffffffffffffffff167f2cdf1508085a46c7241a7d78c5a1ec3d9246d1ab95e1c2a33676d29e17d4222360405160405180910390a3505050505050505050505050565b60075481565b600115156004601c9054906101000a900460ff16151514610ff2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe990613c4e565b60405180910390fd5b600081600360109054906101000a900467ffffffffffffffff1661101691906134f2565b905060008267ffffffffffffffff1611611065576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105c90613d06565b60405180910390fd5b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1611156110d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c990613d98565b60405180910390fd5b600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111c1574262093a80600160008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900467ffffffffffffffff1661117591906134f2565b67ffffffffffffffff1611156111c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b790613e50565b60405180910390fd5b5b6000600360089054906101000a900467ffffffffffffffff1690506000600360109054906101000a900467ffffffffffffffff16905060005b8467ffffffffffffffff168110156112dd57818061121790613b86565b925050828061122590613b86565b93505081600260008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555042600260008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080806112d590613e70565b9150506111fa565b5042600360006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600360086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600360106101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff167f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a460405160405180910390a250505050565b62093a8081565b60065481565b600a60009054906101000a900467ffffffffffffffff1681565b61ea6081565b60026020528060005260406000206000915090508060000154908060010160009054906101000a900467ffffffffffffffff16908060010160089054906101000a900467ffffffffffffffff16905083565b600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d8906134a3565b60405180910390fd5b80600990816114f0919061405a565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b208160405161152091906127ea565b60405180910390a150565b600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060019054906101000a900460ff161590508080156115a85750600160008054906101000a900460ff1660ff16105b806115d557506115b73061244b565b1580156115d45750600160008054906101000a900460ff1660ff16145b5b611614576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160b9061419e565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015611651576001600060016101000a81548160ff0219169083151502179055505b89600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088600060026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508660068190555085600460086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846004601c6101000a81548160ff0219169083151502179055508360099081611785919061405a565b5082600a60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600b90816117be919061405a565b5080156118185760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161180f9190614206565b60405180910390a15b50505050505050505050565b6004601c9054906101000a900460ff1681565b600360189054906101000a900467ffffffffffffffff1681565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600115156004601c9054906101000a900460ff161515146118cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c490613c4e565b60405180910390fd5b60006118d7610805565b90508181111561191c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191390614293565b60405180910390fd5b61ea60835110611961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195890614325565b60405180910390fd5b6119b0333083600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661246e909392919063ffffffff16565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a439190613864565b90506003601881819054906101000a900467ffffffffffffffff1680929190611a6b90613b86565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050838133604051602001611aa79392919061438d565b6040516020818303038152906040528051906020012060016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600001819055508160016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600101819055504260016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603611c3f57600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9318233604051611c329291906143fd565b60405180910390a2611c9c565b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823387604051611c9393929190614472565b60405180910390a25b50505050565b67016345785d8a000081565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d35906134a3565b60405180910390fd5b600081519050611da633308367016345785d8a0000611d5d9190613564565b600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661246e909392919063ffffffff16565b6000600360009054906101000a900467ffffffffffffffff1690506000600360089054906101000a900467ffffffffffffffff1690506000600360109054906101000a900467ffffffffffffffff16905060005b84811015612288576000868281518110611e1757611e166144b0565b5b602002602001015190508467ffffffffffffffff16816040015167ffffffffffffffff1610158015611e57575042816040015167ffffffffffffffff1611155b611e96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8d90614577565b60405180910390fd5b6000801b81602001511480611f4d57506000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663257b363283602001516040518263ffffffff1660e01b8152600401611f079190612b2f565b6020604051808303816000875af1158015611f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4a91906145ac565b14155b611f8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f839061464b565b60405180910390fd5b61ea6081600001515110611fd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcc906146dd565b60405180910390fd5b8380611fe090613b86565b94505080600001518160200151336040516020016120009392919061438d565b60405160208183030381529060405280519060200120600260008667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600001819055508060400151600260008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508060400151945060005b8160600151518110156122735783806120bb90613b86565b9450506000826060015182815181106120d7576120d66144b0565b5b602002602001015190508667ffffffffffffffff168167ffffffffffffffff16101580156121575750600160008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1610155b801561216d5750428167ffffffffffffffff1611155b6121ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a390614795565b60405180910390fd5b85806121b790613b86565b96505084600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080965050808061226b90613e70565b9150506120a3565b5050808061228090613e70565b915050611dfa565b50600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1611156122f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ed90614827565b60405180910390fd5b82600360006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600360086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600360106101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff167f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce60405160405180910390a25050505050565b6124468363a9059cbb60e01b84846040516024016123e4929190614847565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124f7565b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6124f1846323b872dd60e01b85858560405160240161248f93929190614870565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124f7565b50505050565b6000612559826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125be9092919063ffffffff16565b90506000815111156125b957808060200190518101906125799190613ac7565b6125b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125af90614919565b60405180910390fd5b5b505050565b60606125cd84846000856125d6565b90509392505050565b60608247101561261b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612612906149ab565b60405180910390fd5b6126248561244b565b612663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265a90614a17565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161268c9190613838565b60006040518083038185875af1925050503d80600081146126c9576040519150601f19603f3d011682016040523d82523d6000602084013e6126ce565b606091505b50915091506126de8282866126ea565b92505050949350505050565b606083156126fa5782905061274a565b60008351111561270d5782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161274191906127ea565b60405180910390fd5b9392505050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561278b578082015181840152602081019050612770565b8381111561279a576000848401525b50505050565b6000601f19601f8301169050919050565b60006127bc82612751565b6127c6818561275c565b93506127d681856020860161276d565b6127df816127a0565b840191505092915050565b6000602082019050818103600083015261280481846127b1565b905092915050565b600067ffffffffffffffff82169050919050565b6128298161280c565b82525050565b60006020820190506128446000830184612820565b92915050565b6000604051905090565b600080fd5b600080fd5b6128678161280c565b811461287257600080fd5b50565b6000813590506128848161285e565b92915050565b6000602082840312156128a05761289f612854565b5b60006128ae84828501612875565b91505092915050565b6000819050919050565b6128ca816128b7565b82525050565b6000819050919050565b6128e3816128d0565b82525050565b60006060820190506128fe60008301866128c1565b61290b60208301856128da565b6129186040830184612820565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061294b82612920565b9050919050565b61295b81612940565b811461296657600080fd5b50565b60008135905061297881612952565b92915050565b60006020828403121561299457612993612854565b5b60006129a284828501612969565b91505092915050565b60006020820190506129c060008301846128da565b92915050565b60008115159050919050565b6129db816129c6565b81146129e657600080fd5b50565b6000813590506129f8816129d2565b92915050565b600060208284031215612a1457612a13612854565b5b6000612a22848285016129e9565b91505092915050565b612a34816128b7565b8114612a3f57600080fd5b50565b600081359050612a5181612a2b565b92915050565b600080fd5b600081905082602060020282011115612a7857612a77612a57565b5b92915050565b600081905082604060020282011115612a9a57612a99612a57565b5b92915050565b6000806000806000806101608789031215612abe57612abd612854565b5b6000612acc89828a01612a42565b9650506020612add89828a01612a42565b9550506040612aee89828a01612875565b9450506060612aff89828a01612a5c565b93505060a0612b1089828a01612a7e565b925050610120612b2289828a01612a5c565b9150509295509295509295565b6000602082019050612b4460008301846128c1565b92915050565b6000606082019050612b5f60008301866128c1565b612b6c6020830185612820565b612b796040830184612820565b949350505050565b6000819050919050565b6000612ba6612ba1612b9c84612920565b612b81565b612920565b9050919050565b6000612bb882612b8b565b9050919050565b6000612bca82612bad565b9050919050565b612bda81612bbf565b82525050565b6000602082019050612bf56000830184612bd1565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c3d826127a0565b810181811067ffffffffffffffff82111715612c5c57612c5b612c05565b5b80604052505050565b6000612c6f61284a565b9050612c7b8282612c34565b919050565b600067ffffffffffffffff821115612c9b57612c9a612c05565b5b612ca4826127a0565b9050602081019050919050565b82818337600083830152505050565b6000612cd3612cce84612c80565b612c65565b905082815260208101848484011115612cef57612cee612c00565b5b612cfa848285612cb1565b509392505050565b600082601f830112612d1757612d16612bfb565b5b8135612d27848260208601612cc0565b91505092915050565b600060208284031215612d4657612d45612854565b5b600082013567ffffffffffffffff811115612d6457612d63612859565b5b612d7084828501612d02565b91505092915050565b612d8281612940565b82525050565b6000602082019050612d9d6000830184612d79565b92915050565b6000612dae82612bad565b9050919050565b612dbe81612da3565b82525050565b6000602082019050612dd96000830184612db5565b92915050565b6000612dea82612940565b9050919050565b612dfa81612ddf565b8114612e0557600080fd5b50565b600081359050612e1781612df1565b92915050565b6000612e2882612940565b9050919050565b612e3881612e1d565b8114612e4357600080fd5b50565b600081359050612e5581612e2f565b92915050565b6000612e6682612940565b9050919050565b612e7681612e5b565b8114612e8157600080fd5b50565b600081359050612e9381612e6d565b92915050565b60008060008060008060008060006101208a8c031215612ebc57612ebb612854565b5b6000612eca8c828d01612e08565b9950506020612edb8c828d01612e46565b9850506040612eec8c828d01612e84565b9750506060612efd8c828d01612a42565b9650506080612f0e8c828d01612969565b95505060a0612f1f8c828d016129e9565b94505060c08a013567ffffffffffffffff811115612f4057612f3f612859565b5b612f4c8c828d01612d02565b93505060e0612f5d8c828d01612875565b9250506101008a013567ffffffffffffffff811115612f7f57612f7e612859565b5b612f8b8c828d01612d02565b9150509295985092959850929598565b612fa4816129c6565b82525050565b6000602082019050612fbf6000830184612f9b565b92915050565b6000612fd082612bad565b9050919050565b612fe081612fc5565b82525050565b6000602082019050612ffb6000830184612fd7565b92915050565b600067ffffffffffffffff82111561301c5761301b612c05565b5b613025826127a0565b9050602081019050919050565b600061304561304084613001565b612c65565b90508281526020810184848401111561306157613060612c00565b5b61306c848285612cb1565b509392505050565b600082601f83011261308957613088612bfb565b5b8135613099848260208601613032565b91505092915050565b6130ab816128d0565b81146130b657600080fd5b50565b6000813590506130c8816130a2565b92915050565b600080604083850312156130e5576130e4612854565b5b600083013567ffffffffffffffff81111561310357613102612859565b5b61310f85828601613074565b9250506020613120858286016130b9565b9150509250929050565b600067ffffffffffffffff82111561314557613144612c05565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff82111561317b5761317a612c05565b5b602082029050602081019050919050565b600061319f61319a84613160565b612c65565b905080838252602082019050602084028301858111156131c2576131c1612a57565b5b835b818110156131eb57806131d78882612875565b8452602084019350506020810190506131c4565b5050509392505050565b600082601f83011261320a57613209612bfb565b5b813561321a84826020860161318c565b91505092915050565b60006080828403121561323957613238613156565b5b6132436080612c65565b9050600082013567ffffffffffffffff8111156132635761326261315b565b5b61326f84828501613074565b600083015250602061328384828501612a42565b602083015250604061329784828501612875565b604083015250606082013567ffffffffffffffff8111156132bb576132ba61315b565b5b6132c7848285016131f5565b60608301525092915050565b60006132e66132e18461312a565b612c65565b9050808382526020820190506020840283018581111561330957613308612a57565b5b835b8181101561335057803567ffffffffffffffff81111561332e5761332d612bfb565b5b80860161333b8982613223565b8552602085019450505060208101905061330b565b5050509392505050565b600082601f83011261336f5761336e612bfb565b5b813561337f8482602086016132d3565b91505092915050565b60006020828403121561339e5761339d612854565b5b600082013567ffffffffffffffff8111156133bc576133bb612859565b5b6133c88482850161335a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061341857607f821691505b60208210810361342b5761342a6133d1565b5b50919050565b7f50726f6f664f66456666696369656e63793a3a6f6e6c7954727573746564536560008201527f7175656e6365723a206f6e6c7920747275737465642073657175656e63657200602082015250565b600061348d603f8361275c565b915061349882613431565b604082019050919050565b600060208201905081810360008301526134bc81613480565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006134fd8261280c565b91506135088361280c565b92508267ffffffffffffffff03821115613525576135246134c3565b5b828201905092915050565b600061353b8261280c565b91506135468361280c565b925082821015613559576135586134c3565b5b828203905092915050565b600061356f826128d0565b915061357a836128d0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156135b3576135b26134c3565b5b828202905092915050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f626174636820646f6573206e6f74206d61746368000000000000000000000000602082015250565b600061361a60348361275c565b9150613625826135be565b604082019050919050565b600060208201905081810360008301526136498161360d565b9050919050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f626174636820646f6573206e6f742068617665206265656e2073657175656e6360208201527f6564000000000000000000000000000000000000000000000000000000000000604082015250565b60006136d260428361275c565b91506136dd82613650565b606082019050919050565b60006020820190508181036000830152613701816136c5565b9050919050565b6000819050919050565b61372361371e826128b7565b613708565b82525050565b60008160c01b9050919050565b600061374182613729565b9050919050565b6137596137548261280c565b613736565b82525050565b600061376b828b613712565b60208201915061377b828a613712565b60208201915061378b8289613712565b60208201915061379b8288613712565b6020820191506137ab8287613712565b6020820191506137bb8286613748565b6008820191506137cb8285613748565b6008820191506137db8284613748565b6008820191508190509998505050505050505050565b600081519050919050565b600081905092915050565b6000613812826137f1565b61381c81856137fc565b935061382c81856020860161276d565b80840191505092915050565b60006138448284613807565b915081905092915050565b60008151905061385e81612a2b565b92915050565b60006020828403121561387a57613879612854565b5b60006138888482850161384f565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006138cb826128d0565b91506138d6836128d0565b9250826138e6576138e5613891565b5b828206905092915050565b6138fd60408383612cb1565b5050565b600060029050919050565b600081905092915050565b6000819050919050565b61392d60408383612cb1565b5050565b600061393d8383613921565b60408301905092915050565b600082905092915050565b6000604082019050919050565b61396a81613901565b613974818461390c565b925061397f82613917565b8060005b838110156139b8576139958284613949565b61399f8782613931565b96506139aa83613954565b925050600181019050613983565b505050505050565b600060019050919050565b600081905092915050565b6000819050919050565b6139e9816128d0565b82525050565b60006139fb83836139e0565b60208301905092915050565b6000602082019050919050565b613a1d816139c0565b613a2781846139cb565b9250613a32826139d6565b8060005b83811015613a63578151613a4a87826139ef565b9650613a5583613a07565b925050600181019050613a36565b505050505050565b600061012082019050613a8160008301876138f1565b613a8e6040830186613961565b613a9b60c08301856138f1565b613aa9610100830184613a14565b95945050505050565b600081519050613ac1816129d2565b92915050565b600060208284031215613add57613adc612854565b5b6000613aeb84828501613ab2565b91505092915050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f494e56414c49445f50524f4f4600000000000000000000000000000000000000602082015250565b6000613b50602d8361275c565b9150613b5b82613af4565b604082019050919050565b60006020820190508181036000830152613b7f81613b43565b9050919050565b6000613b918261280c565b915067ffffffffffffffff8203613bab57613baa6134c3565b5b600182019050919050565b7f50726f6f664f66456666696369656e63793a3a6973466f72636542617463684160008201527f6c6c6f7765643a206f6e6c7920696620666f726365206261746368206973206160208201527f7661696c61626c65000000000000000000000000000000000000000000000000604082015250565b6000613c3860488361275c565b9150613c4382613bb6565b606082019050919050565b60006020820190508181036000830152613c6781613c2b565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a204d75737420666f726365206174206c6561737420312062617460208201527f6368000000000000000000000000000000000000000000000000000000000000604082015250565b6000613cf060428361275c565b9150613cfb82613c6e565b606082019050919050565b60006020820190508181036000830152613d1f81613ce3565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a20466f72636520626174636820696e76616c6964000000000000602082015250565b6000613d82603a8361275c565b9150613d8d82613d26565b604082019050919050565b60006020820190508181036000830152613db181613d75565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a20466f72636564206261746368206973206e6f7420696e20746960208201527f6d656f757420706572696f640000000000000000000000000000000000000000604082015250565b6000613e3a604c8361275c565b9150613e4582613db8565b606082019050919050565b60006020820190508181036000830152613e6981613e2d565b9050919050565b6000613e7b826128d0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ead57613eac6134c3565b5b600182019050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613f1a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613edd565b613f248683613edd565b95508019841693508086168417925050509392505050565b6000613f57613f52613f4d846128d0565b612b81565b6128d0565b9050919050565b6000819050919050565b613f7183613f3c565b613f85613f7d82613f5e565b848454613eea565b825550505050565b600090565b613f9a613f8d565b613fa5818484613f68565b505050565b5b81811015613fc957613fbe600082613f92565b600181019050613fab565b5050565b601f82111561400e57613fdf81613eb8565b613fe884613ecd565b81016020851015613ff7578190505b61400b61400385613ecd565b830182613faa565b50505b505050565b600082821c905092915050565b600061403160001984600802614013565b1980831691505092915050565b600061404a8383614020565b9150826002028217905092915050565b61406382612751565b67ffffffffffffffff81111561407c5761407b612c05565b5b6140868254613400565b614091828285613fcd565b600060209050601f8311600181146140c457600084156140b2578287015190505b6140bc858261403e565b865550614124565b601f1984166140d286613eb8565b60005b828110156140fa578489015182556001820191506020850194506020810190506140d5565b868310156141175784890151614113601f891682614020565b8355505b6001600288020188555050505b505050505050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614188602e8361275c565b91506141938261412c565b604082019050919050565b600060208201905081810360008301526141b78161417b565b9050919050565b6000819050919050565b600060ff82169050919050565b60006141f06141eb6141e6846141be565b612b81565b6141c8565b9050919050565b614200816141d5565b82525050565b600060208201905061421b60008301846141f7565b92915050565b7f50726f6f664f66456666696369656e63793a3a666f72636542617463683a206e60008201527f6f7420656e6f756768206d617469630000000000000000000000000000000000602082015250565b600061427d602f8361275c565b915061428882614221565b604082019050919050565b600060208201905081810360008301526142ac81614270565b9050919050565b7f50726f6f664f66456666696369656e63793a3a666f72636542617463683a205460008201527f72616e73616374696f6e73206279746573206f766572666c6f77000000000000602082015250565b600061430f603a8361275c565b915061431a826142b3565b604082019050919050565b6000602082019050818103600083015261433e81614302565b9050919050565b60008160601b9050919050565b600061435d82614345565b9050919050565b600061436f82614352565b9050919050565b61438761438282612940565b614364565b82525050565b60006143998286613807565b91506143a58285613712565b6020820191506143b58284614376565b601482019150819050949350505050565b600082825260208201905092915050565b50565b60006143e76000836143c6565b91506143f2826143d7565b600082019050919050565b600060608201905061441260008301856128c1565b61441f6020830184612d79565b8181036040830152614430816143da565b90509392505050565b6000614444826137f1565b61444e81856143c6565b935061445e81856020860161276d565b614467816127a0565b840191505092915050565b600060608201905061448760008301866128c1565b6144946020830185612d79565b81810360408301526144a68184614439565b9050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a2054696d657374616d70206d75737420626520696e736964652072616e60208201527f6765000000000000000000000000000000000000000000000000000000000000604082015250565b600061456160428361275c565b915061456c826144df565b606082019050919050565b6000602082019050818103600083015261459081614554565b9050919050565b6000815190506145a6816130a2565b92915050565b6000602082840312156145c2576145c1612854565b5b60006145d084828501614597565b91505092915050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20476c6f62616c206578697420726f6f74206d75737420657869737400602082015250565b6000614635603f8361275c565b9150614640826145d9565b604082019050919050565b6000602082019050818103600083015261466481614628565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a205472616e73616374696f6e73206279746573206f766572666c6f7700602082015250565b60006146c7603f8361275c565b91506146d28261466b565b604082019050919050565b600060208201905081810360008301526146f6816146ba565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20466f7263656420626174636865732074696d657374616d70206d757360208201527f7420626520696e736964652072616e6765000000000000000000000000000000604082015250565b600061477f60518361275c565b915061478a826146fd565b606082019050919050565b600060208201905081810360008301526147ae81614772565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20466f7263652062617463686573206f766572666c6f77000000000000602082015250565b6000614811603a8361275c565b915061481c826147b5565b604082019050919050565b6000602082019050818103600083015261484081614804565b9050919050565b600060408201905061485c6000830185612d79565b61486960208301846128da565b9392505050565b60006060820190506148856000830186612d79565b6148926020830185612d79565b61489f60408301846128da565b949350505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614903602a8361275c565b915061490e826148a7565b604082019050919050565b60006020820190508181036000830152614932816148f6565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061499560268361275c565b91506149a082614939565b604082019050919050565b600060208201905081810360008301526149c481614988565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614a01601d8361275c565b9150614a0c826149cb565b602082019050919050565b60006020820190508181036000830152614a30816149f4565b905091905056fea264697066735822122096d3f605efd2603a322512eaacca9427459d9f6977009f0fce10ca96f79f16da64736f6c634300080f0033 \ No newline at end of file diff --git a/etherman/smartcontracts/bridge/bridge.go b/etherman/smartcontracts/bridge/bridge.go deleted file mode 100644 index 9f79046c61..0000000000 --- a/etherman/smartcontracts/bridge/bridge.go +++ /dev/null @@ -1,1230 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package bridge - -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 -) - -// BridgeMetaData contains all meta data concerning the Bridge contract. -var BridgeMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"depositCount\",\"type\":\"uint32\"}],\"name\":\"BridgeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ClaimEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"wrappedTokenAddress\",\"type\":\"address\"}],\"name\":\"NewWrappedToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAINNET_NETWORK_ID\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"permitData\",\"type\":\"bytes\"}],\"name\":\"bridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"smtProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"mainnetExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"rollupExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimNullifier\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDepositRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"name\":\"getLeafValue\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"}],\"name\":\"getTokenWrappedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalExitRootManager\",\"outputs\":[{\"internalType\":\"contractIGlobalExitRootManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_networkID\",\"type\":\"uint32\"},{\"internalType\":\"contractIGlobalExitRootManager\",\"name\":\"_globalExitRootManager\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"networkID\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"}],\"name\":\"precalculatedWrapperAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"tokenInfoToWrappedToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"smtProof\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint64\",\"name\":\"index\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"verifyMerkleProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"wrappedTokenToTokenInfo\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50614adb806100206000396000f3fe608060405260043610620001075760003560e01c80635d5d326f1162000095578063bab161bf1162000060578063bab161bf1462000414578063d02103ca1462000449578063e73758811462000478578063ed6be5c914620004ac57600080fd5b80635d5d326f146200035e57806381b1c17414620003835780638624c35c14620003ca578063b7e6a7d414620003ef57600080fd5b80633ae0504711620000d65780633ae05047146200023a5780633da816821462000252578063508935f814620002885780635a64a1da14620002a157600080fd5b806322e95f2c146200010c5780632dfdf0b5146200015b5780632f3a3d5d1462000182578063318aee3d14620001b1575b600080fd5b3480156200011957600080fd5b50620001316200012b3660046200278e565b620004c3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200016857600080fd5b506200017360415481565b60405190815260200162000152565b3480156200018f57600080fd5b50604754620001319073ffffffffffffffffffffffffffffffffffffffff1681565b348015620001be57600080fd5b5062000208620001d0366004620027ca565b60456020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff90911660208301520162000152565b3480156200024757600080fd5b506200017362000566565b3480156200025f57600080fd5b506200027762000271366004620028e9565b62000640565b604051901515815260200162000152565b6200029f6200029936600462002957565b62000740565b005b348015620002ae57600080fd5b5062000173620002c036600462002a13565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e098891b81166020808401919091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000006060998a1b811660248501529790991b1660388201529390951b909316603c830152605082015260708082019290925282518082039092018252609001909152805191012090565b3480156200036b57600080fd5b506200029f6200037d36600462002b2b565b62000d2a565b3480156200039057600080fd5b5062000131620003a236600462002c12565b60446020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620003d757600080fd5b506200029f620003e93660046200278e565b620017d9565b348015620003fc57600080fd5b50620001316200040e3660046200278e565b62001a57565b3480156200042157600080fd5b50604254620004339063ffffffff1681565b60405163ffffffff909116815260200162000152565b3480156200045657600080fd5b50604654620001319073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200048557600080fd5b50620002776200049736600462002c12565b60436020526000908152604090205460ff1681565b348015620004b957600080fd5b5062000433600081565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166024830152825160188184030181526038909201835281519181019190912060009081526044909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b6041546000908190815b6020811015620006385781600116600103620005d057600181602081106200059c576200059c62002c2c565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925062000614565b8260218260208110620005e757620005e762002c2c565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b6200062160028362002c8a565b9150806200062f8162002cc6565b91505062000570565b509092915050565b60008467ffffffffffffffff8416825b6020811015620007335781600116600103620006bd578681815181106200067b576200067b62002c2c565b6020026020010151836040516020016200069f929190918252602082015260400190565b6040516020818303038152906040528051906020012092506200070f565b82878281518110620006d357620006d362002c2c565b6020026020010151604051602001620006f6929190918252602082015260400190565b6040516020818303038152906040528051906020012092505b6200071c60028362002c8a565b9150806200072a8162002cc6565b91505062000650565b5050909114949350505050565b60425463ffffffff90811690861603620007e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4272696467653a3a6272696467653a2044455354494e4154494f4e5f43414e5460448201527f5f42455f495453454c460000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600080606073ffffffffffffffffffffffffffffffffffffffff89166200089d5785341462000893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4272696467653a3a6272696467653a20414d4f554e545f444f45535f4e4f545f60448201527f4d415443485f4d53475f56414c554500000000000000000000000000000000006064820152608401620007d8565b6000915062000bb1565b73ffffffffffffffffffffffffffffffffffffffff808a1660009081526045602090815260409182902082518084019093525463ffffffff81168352640100000000900490921691810182905290156200099e576040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810188905273ffffffffffffffffffffffffffffffffffffffff8b1690639dc29fac906044016020604051808303816000875af115801562000965573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200098b919062002d01565b5060208101518151909450925062000baf565b8415620009b357620009b38a88888862001b20565b620009d773ffffffffffffffffffffffffffffffffffffffff8b1633308a62001f4b565b899350604260009054906101000a900463ffffffff1692508973ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000a3b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000a83919081019062002da0565b8a73ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000acf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262000b17919081019062002da0565b8b73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000b63573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b89919062002de9565b60405160200162000b9d9392919062002e55565b60405160208183030381529060405291505b505b7ff0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a82848a8a8a8660415460405162000bf0979695949392919062002e92565b60405180910390a18051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e087811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608a811b82166024860152918f901b90921660388401528c901b16603c820152605081018a9052607080820193909352815180820390930183526090019052805191012062000ca4906200202f565b60465473ffffffffffffffffffffffffffffffffffffffff166333d6247d62000ccc62000566565b6040518263ffffffff1660e01b815260040162000ceb91815260200190565b600060405180830381600087803b15801562000d0657600080fd5b505af115801562000d1b573d6000803e3d6000fd5b50505050505050505050505050565b63ffffffff891660009081526043602052604090205460ff161562000dac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4272696467653a3a636c61696d3a20414c52454144595f434c41494d454400006044820152606401620007d8565b6046546040805160208082018c90528183018b9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915273ffffffffffffffffffffffffffffffffffffffff9091169063257b3632906084016020604051808303816000875af115801562000e45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e6b919062002eff565b60000362000efc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4272696467653a3a636c61696d3a20474c4f42414c5f455849545f524f4f545f60448201527f444f45535f4e4f545f4d415443480000000000000000000000000000000000006064820152608401620007d8565b60425463ffffffff85811691161462000f98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4272696467653a3a636c61696d3a2044455354494e4154494f4e5f4e4554574f60448201527f524b5f444f45535f4e4f545f4d415443480000000000000000000000000000006064820152608401620007d8565b60425463ffffffff16620010c9578051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200105b908b8b63ffffffff168a62000640565b620010c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b620011e6565b8051602080830191909120604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08b811b8216838701527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c811b82166024860152918b901b909216603884015288901b16603c8201526050810186905260708082019390935281518082039093018352609001905280519101206200117e908b8b63ffffffff168b62000640565b620011e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4272696467653a3a636c61696d3a20534d545f494e56414c49440000000000006044820152606401620007d8565b63ffffffff8916600090815260436020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905573ffffffffffffffffffffffffffffffffffffffff851662001357576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff851690849060405162001279919062002f19565b60006040518083038185875af1925050503d8060008114620012b8576040519150601f19603f3d011682016040523d82523d6000602084013e620012bd565b606091505b505090508062001350576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4272696467653a3a636c61696d3a204554485f5452414e534645525f4641494c60448201527f45440000000000000000000000000000000000000000000000000000000000006064820152608401620007d8565b5062001762565b60425463ffffffff9081169087160362001394576200138e73ffffffffffffffffffffffffffffffffffffffff86168484620021a8565b62001762565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e088901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152604490935291205490915073ffffffffffffffffffffffffffffffffffffffff1680620016c1576047546000906200147f9073ffffffffffffffffffffffffffffffffffffffff168462002200565b90506000806000868060200190518101906200149c919062002f37565b9250925092508373ffffffffffffffffffffffffffffffffffffffff16636c9452218484848d8d6040518663ffffffff1660e01b8152600401620014e595949392919062002fb8565b600060405180830381600087803b1580156200150057600080fd5b505af115801562001515573d6000803e3d6000fd5b50505050836044600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808d63ffffffff1681526020018c73ffffffffffffffffffffffffffffffffffffffff16815250604560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507fccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d598c8c86604051620016af9392919063ffffffff93909316835273ffffffffffffffffffffffffffffffffffffffff918216602084015216604082015260600190565b60405180910390a1505050506200175f565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690528216906340c10f19906044016020604051808303816000875af115801562001737573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200175d919062002d01565b505b50505b6040805163ffffffff8b811682528816602082015273ffffffffffffffffffffffffffffffffffffffff87811682840152851660608201526080810184905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a150505050505050505050565b600054610100900460ff1615808015620017fa5750600054600160ff909116105b80620018165750303b15801562001816575060005460ff166001145b620018a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620007d8565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200190357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b604280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8516179055604680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055604051620019819062002736565b604051809103906000f0801580156200199e573d6000803e3d6000fd5b50604780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055620019ee620022e0565b801562001a5257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b1660248201526000908190603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012060475490915062001b189073ffffffffffffffffffffffffffffffffffffffff168262002428565b949350505050565b600062001b6383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620024ac92505050565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fd505accf000000000000000000000000000000000000000000000000000000001462001c12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4272696467653a3a5f7065726d69743a204e4f545f56414c49445f43414c4c006044820152606401620007d8565b600080808080808062001c29896004818d62003018565b81019062001c38919062003044565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001d03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4272696467653a3a5f7065726d69743a205045524d49545f4f574e45525f4d5560448201527f53545f42455f5448455f53454e444552000000000000000000000000000000006064820152608401620007d8565b73ffffffffffffffffffffffffffffffffffffffff8616301462001daa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4272696467653a3a5f7065726d69743a205350454e4445525f4d5553545f424560448201527f5f544849530000000000000000000000000000000000000000000000000000006064820152608401620007d8565b8a851462001e3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4272696467653a3a5f7065726d69743a205045524d49545f414d4f554e545f4460448201527f4f45535f4e4f545f4d41544348000000000000000000000000000000000000006064820152608401620007d8565b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162001ef6919062002f19565b6000604051808303816000865af19150503d806000811462001f35576040519150601f19603f3d011682016040523d82523d6000602084013e62001f3a565b606091505b505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620020299085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620024b3565b50505050565b8060016200204060206002620031f5565b6200204c919062003203565b60415410620020de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4465706f736974436f6e74726163743a5f6465706f7369743a204d45524b4c4560448201527f5f545245455f46554c4c000000000000000000000000000000000000000000006064820152608401620007d8565b600160416000828254620020f391906200321d565b909155505060415460005b60208110156200219d5781600116600103620021335782600182602081106200212b576200212b62002c2c565b015550505050565b6001816020811062002149576200214962002c2c565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925060028262002186919062002c8a565b915080620021948162002cc6565b915050620020fe565b5062001a5262003238565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001a529084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640162001fa6565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f591505073ffffffffffffffffffffffffffffffffffffffff811662000560576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f455243313136373a2063726561746532206661696c65640000000000000000006044820152606401620007d8565b600054610100900460ff1662002379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620007d8565b60005b6200238a6001602062003203565b811015620024255760218160208110620023a857620023a862002c2c565b015460218260208110620023c057620023c062002c2c565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206021826001620023fb91906200321d565b602081106200240e576200240e62002c2c565b0155806200241c8162002cc6565b9150506200237c565b50565b6000620024a58383306040517f3d602d80600a3d3981f3363d3d373d3d3d363d730000000000000000000000008152606093841b60148201527f5af43d82803e903d91602b57fd5bf3ff000000000000000000000000000000006028820152921b6038830152604c8201526037808220606c830152605591012090565b9392505050565b6020015190565b600062002517826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620025c69092919063ffffffff16565b80519091501562001a52578080602001905181019062002538919062002d01565b62001a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620007d8565b606062001b1884846000858573ffffffffffffffffffffffffffffffffffffffff85163b62002652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620007d8565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516200267d919062002f19565b60006040518083038185875af1925050503d8060008114620026bc576040519150601f19603f3d011682016040523d82523d6000602084013e620026c1565b606091505b5091509150620026d3828286620026de565b979650505050505050565b60608315620026ef575081620024a5565b825115620027005782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620007d8919062003267565b611829806200327d83390190565b803563ffffffff811681146200275957600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146200242557600080fd5b803562002759816200275e565b60008060408385031215620027a257600080fd5b620027ad8362002744565b91506020830135620027bf816200275e565b809150509250929050565b600060208284031215620027dd57600080fd5b8135620024a5816200275e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620028635762002863620027ea565b604052919050565b600082601f8301126200287d57600080fd5b8135602067ffffffffffffffff8211156200289c576200289c620027ea565b8160051b620028ad82820162002819565b9283528481018201928281019087851115620028c857600080fd5b83870192505b84831015620026d357823582529183019190830190620028ce565b600080600080608085870312156200290057600080fd5b84359350602085013567ffffffffffffffff808211156200292057600080fd5b6200292e888389016200286b565b94506040870135915080821682146200294657600080fd5b509396929550929360600135925050565b60008060008060008060a087890312156200297157600080fd5b86356200297e816200275e565b95506200298e6020880162002744565b94506040870135620029a0816200275e565b935060608701359250608087013567ffffffffffffffff80821115620029c557600080fd5b818901915089601f830112620029da57600080fd5b813581811115620029ea57600080fd5b8a6020828501011115620029fd57600080fd5b6020830194508093505050509295509295509295565b60008060008060008060c0878903121562002a2d57600080fd5b62002a388762002744565b9550602087013562002a4a816200275e565b945062002a5a6040880162002744565b9350606087013562002a6c816200275e565b9598949750929560808101359460a0909101359350915050565b600067ffffffffffffffff82111562002aa35762002aa3620027ea565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002ae157600080fd5b813562002af862002af28262002a86565b62002819565b81815284602083860101111562002b0e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d03121562002b4c57600080fd5b8a3567ffffffffffffffff8082111562002b6557600080fd5b62002b738e838f016200286b565b9b5062002b8360208e0162002744565b9a5060408d0135995060608d0135985062002ba160808e0162002744565b975062002bb160a08e0162002781565b965062002bc160c08e0162002744565b955062002bd160e08e0162002781565b94506101008d013593506101208d013591508082111562002bf157600080fd5b5062002c008d828e0162002acf565b9150509295989b9194979a5092959850565b60006020828403121562002c2557600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008262002cc1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002cfa5762002cfa62002c5b565b5060010190565b60006020828403121562002d1457600080fd5b81518015158114620024a557600080fd5b60005b8381101562002d4257818101518382015260200162002d28565b83811115620020295750506000910152565b600082601f83011262002d6657600080fd5b815162002d7762002af28262002a86565b81815284602083860101111562002d8d57600080fd5b62001b1882602083016020870162002d25565b60006020828403121562002db357600080fd5b815167ffffffffffffffff81111562002dcb57600080fd5b62001b188482850162002d54565b60ff811681146200242557600080fd5b60006020828403121562002dfc57600080fd5b8151620024a58162002dd9565b6000815180845262002e2381602086016020860162002d25565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062002e6a606083018662002e09565b828103602084015262002e7e818662002e09565b91505060ff83166040830152949350505050565b600063ffffffff808a16835273ffffffffffffffffffffffffffffffffffffffff808a166020850152818916604085015280881660608501525085608084015260e060a084015262002ee860e084018662002e09565b915080841660c08401525098975050505050505050565b60006020828403121562002f1257600080fd5b5051919050565b6000825162002f2d81846020870162002d25565b9190910192915050565b60008060006060848603121562002f4d57600080fd5b835167ffffffffffffffff8082111562002f6657600080fd5b62002f748783880162002d54565b9450602086015191508082111562002f8b57600080fd5b5062002f9a8682870162002d54565b925050604084015162002fad8162002dd9565b809150509250925092565b60a08152600062002fcd60a083018862002e09565b828103602084015262002fe1818862002e09565b60ff969096166040840152505073ffffffffffffffffffffffffffffffffffffffff92909216606083015260809091015292915050565b600080858511156200302957600080fd5b838611156200303757600080fd5b5050820193919092039150565b600080600080600080600060e0888a0312156200306057600080fd5b87356200306d816200275e565b965060208801356200307f816200275e565b9550604088013594506060880135935060808801356200309f8162002dd9565b9699959850939692959460a0840135945060c09093013592915050565b600181815b808511156200311b57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620030ff57620030ff62002c5b565b808516156200310d57918102915b93841c9390800290620030c1565b509250929050565b600082620031345750600162000560565b81620031435750600062000560565b81600181146200315c5760028114620031675762003187565b600191505062000560565b60ff8411156200317b576200317b62002c5b565b50506001821b62000560565b5060208310610133831016604e8410600b8410161715620031ac575081810a62000560565b620031b88383620030bc565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620031ed57620031ed62002c5b565b029392505050565b6000620024a5838362003123565b60008282101562003218576200321862002c5b565b500390565b6000821982111562003233576200323362002c5b565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b602081526000620024a5602083018462002e0956fe60806040523480156200001157600080fd5b50600054610100900460ff1615808015620000335750600054600160ff909116105b8062000063575062000050306200013d60201b6200080a1760201c565b15801562000063575060005460ff166001145b620000cb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000ef576000805461ff0019166101001790555b801562000136576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b506200014c565b6001600160a01b03163b151590565b6116cd806200015c6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80636c94522111610097578063a3c573eb11610066578063a3c573eb1461021c578063a457c2d714610261578063a9059cbb14610274578063dd62ed3e1461028757600080fd5b80636c945221146101b657806370a08231146101cb57806395d89b41146102015780639dc29fac1461020957600080fd5b806323b872dd116100d357806323b872dd1461014d578063313ce56714610160578063395093511461019057806340c10f19146101a357600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b6101026102cd565b60405161010f91906111c0565b60405180910390f35b61012b61012636600461125c565b61035f565b604051901515815260200161010f565b6035545b60405190815260200161010f565b61012b61015b366004611286565b610377565b60655474010000000000000000000000000000000000000000900460ff1660405160ff909116815260200161010f565b61012b61019e36600461125c565b61039b565b61012b6101b136600461125c565b6103e7565b6101c96101c436600461139c565b610483565b005b61013f6101d9366004611431565b73ffffffffffffffffffffffffffffffffffffffff1660009081526033602052604090205490565b61010261068e565b61012b61021736600461125c565b61069d565b60655461023c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010f565b61012b61026f36600461125c565b61072b565b61012b61028236600461125c565b6107fc565b61013f610295366004611453565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260346020908152604080832093909416825291909152205490565b6060603680546102dc90611486565b80601f016020809104026020016040519081016040528092919081815260200182805461030890611486565b80156103555780601f1061032a57610100808354040283529160200191610355565b820191906000526020600020905b81548152906001019060200180831161033857829003601f168201915b5050505050905090565b60003361036d818585610826565b5060019392505050565b6000336103858582856109da565b610390858585610ab1565b506001949350505050565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061036d90829086906103e2908790611508565b610826565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f42524944474500000000000000000060448201526064015b60405180910390fd5b61047a8383610d64565b50600192915050565b600054610100900460ff16158080156104a35750600054600160ff909116105b806104bd5750303b1580156104bd575060005460ff166001145b610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610467565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105b18686610e85565b606580547fffffffffffffffffffffff00000000000000000000000000000000000000000016337fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16177401000000000000000000000000000000000000000060ff8716021790556106238383610d64565b801561068657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6060603780546102dc90611486565b60655460009073ffffffffffffffffffffffffffffffffffffffff163314610721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f546f6b656e577261707065643a4e4f545f4252494447450000000000000000006044820152606401610467565b61047a8383610f26565b33600081815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610467565b6103908286868403610826565b60003361036d818585610ab1565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff83166108c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff821661096b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603460209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610aab5781811015610a9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610467565b610aab8484848403610826565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610b54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff8216610bf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604090205481811015610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260336020526040808220858503905591851681529081208054849290610cf1908490611508565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d5791815260200190565b60405180910390a3610aab565b73ffffffffffffffffffffffffffffffffffffffff8216610de1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610467565b8060356000828254610df39190611508565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526033602052604081208054839290610e2d908490611508565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b5050565b600054610100900460ff16610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b610e818282611110565b73ffffffffffffffffffffffffffffffffffffffff8216610fc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603360205260409020548181101561107f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610467565b73ffffffffffffffffffffffffffffffffffffffff831660009081526033602052604081208383039055603580548492906110bb908490611520565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016109cd565b505050565b600054610100900460ff166111a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610467565b60366111b3838261157d565b50603761110b828261157d565b600060208083528351808285015260005b818110156111ed578581018301518582016040015282016111d1565b818111156111ff576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125757600080fd5b919050565b6000806040838503121561126f57600080fd5b61127883611233565b946020939093013593505050565b60008060006060848603121561129b57600080fd5b6112a484611233565b92506112b260208501611233565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261130257600080fd5b813567ffffffffffffffff8082111561131d5761131d6112c2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611363576113636112c2565b8160405283815286602085880101111561137c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113b457600080fd5b853567ffffffffffffffff808211156113cc57600080fd5b6113d889838a016112f1565b965060208801359150808211156113ee57600080fd5b506113fb888289016112f1565b945050604086013560ff8116811461141257600080fd5b925061142060608701611233565b949793965091946080013592915050565b60006020828403121561144357600080fd5b61144c82611233565b9392505050565b6000806040838503121561146657600080fd5b61146f83611233565b915061147d60208401611233565b90509250929050565b600181811c9082168061149a57607f821691505b6020821081036114d3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561151b5761151b6114d9565b500190565b600082821015611532576115326114d9565b500390565b601f82111561110b57600081815260208120601f850160051c8101602086101561155e5750805b601f850160051c820191505b818110156106865782815560010161156a565b815167ffffffffffffffff811115611597576115976112c2565b6115ab816115a58454611486565b84611537565b602080601f8311600181146115fe57600084156115c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610686565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561164b5788860151825594840194600190910190840161162c565b508582101561168757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220dbe4ae42463287341e0a5f486d0158c3cfe64d0921e8610c4a99cd4b5787807264736f6c634300080f0033a2646970667358221220f3d36271f729414602eb75fce97fce3c572e0ba1fc2f9e47c28ca6783d60b46764736f6c634300080f0033", -} - -// BridgeABI is the input ABI used to generate the binding from. -// Deprecated: Use BridgeMetaData.ABI instead. -var BridgeABI = BridgeMetaData.ABI - -// BridgeBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use BridgeMetaData.Bin instead. -var BridgeBin = BridgeMetaData.Bin - -// DeployBridge deploys a new Ethereum contract, binding an instance of Bridge to it. -func DeployBridge(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Bridge, error) { - parsed, err := BridgeMetaData.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(BridgeBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Bridge{BridgeCaller: BridgeCaller{contract: contract}, BridgeTransactor: BridgeTransactor{contract: contract}, BridgeFilterer: BridgeFilterer{contract: contract}}, nil -} - -// Bridge is an auto generated Go binding around an Ethereum contract. -type Bridge struct { - BridgeCaller // Read-only binding to the contract - BridgeTransactor // Write-only binding to the contract - BridgeFilterer // Log filterer for contract events -} - -// BridgeCaller is an auto generated read-only Go binding around an Ethereum contract. -type BridgeCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. -type BridgeTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type BridgeFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BridgeSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type BridgeSession struct { - Contract *Bridge // 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 -} - -// BridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type BridgeCallerSession struct { - Contract *BridgeCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// BridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type BridgeTransactorSession struct { - Contract *BridgeTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// BridgeRaw is an auto generated low-level Go binding around an Ethereum contract. -type BridgeRaw struct { - Contract *Bridge // Generic contract binding to access the raw methods on -} - -// BridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type BridgeCallerRaw struct { - Contract *BridgeCaller // Generic read-only contract binding to access the raw methods on -} - -// BridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type BridgeTransactorRaw struct { - Contract *BridgeTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewBridge creates a new instance of Bridge, bound to a specific deployed contract. -func NewBridge(address common.Address, backend bind.ContractBackend) (*Bridge, error) { - contract, err := bindBridge(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Bridge{BridgeCaller: BridgeCaller{contract: contract}, BridgeTransactor: BridgeTransactor{contract: contract}, BridgeFilterer: BridgeFilterer{contract: contract}}, nil -} - -// NewBridgeCaller creates a new read-only instance of Bridge, bound to a specific deployed contract. -func NewBridgeCaller(address common.Address, caller bind.ContractCaller) (*BridgeCaller, error) { - contract, err := bindBridge(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &BridgeCaller{contract: contract}, nil -} - -// NewBridgeTransactor creates a new write-only instance of Bridge, bound to a specific deployed contract. -func NewBridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*BridgeTransactor, error) { - contract, err := bindBridge(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &BridgeTransactor{contract: contract}, nil -} - -// NewBridgeFilterer creates a new log filterer instance of Bridge, bound to a specific deployed contract. -func NewBridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*BridgeFilterer, error) { - contract, err := bindBridge(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &BridgeFilterer{contract: contract}, nil -} - -// bindBridge binds a generic wrapper to an already deployed contract. -func bindBridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(BridgeABI)) - 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 (_Bridge *BridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Bridge.Contract.BridgeCaller.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 (_Bridge *BridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Bridge.Contract.BridgeTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Bridge *BridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Bridge.Contract.BridgeTransactor.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 (_Bridge *BridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Bridge.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 (_Bridge *BridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Bridge.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Bridge *BridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Bridge.Contract.contract.Transact(opts, method, params...) -} - -// MAINNETNETWORKID is a free data retrieval call binding the contract method 0xed6be5c9. -// -// Solidity: function MAINNET_NETWORK_ID() view returns(uint32) -func (_Bridge *BridgeCaller) MAINNETNETWORKID(opts *bind.CallOpts) (uint32, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "MAINNET_NETWORK_ID") - - if err != nil { - return *new(uint32), err - } - - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) - - return out0, err - -} - -// MAINNETNETWORKID is a free data retrieval call binding the contract method 0xed6be5c9. -// -// Solidity: function MAINNET_NETWORK_ID() view returns(uint32) -func (_Bridge *BridgeSession) MAINNETNETWORKID() (uint32, error) { - return _Bridge.Contract.MAINNETNETWORKID(&_Bridge.CallOpts) -} - -// MAINNETNETWORKID is a free data retrieval call binding the contract method 0xed6be5c9. -// -// Solidity: function MAINNET_NETWORK_ID() view returns(uint32) -func (_Bridge *BridgeCallerSession) MAINNETNETWORKID() (uint32, error) { - return _Bridge.Contract.MAINNETNETWORKID(&_Bridge.CallOpts) -} - -// ClaimNullifier is a free data retrieval call binding the contract method 0xe7375881. -// -// Solidity: function claimNullifier(uint256 ) view returns(bool) -func (_Bridge *BridgeCaller) ClaimNullifier(opts *bind.CallOpts, arg0 *big.Int) (bool, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "claimNullifier", arg0) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// ClaimNullifier is a free data retrieval call binding the contract method 0xe7375881. -// -// Solidity: function claimNullifier(uint256 ) view returns(bool) -func (_Bridge *BridgeSession) ClaimNullifier(arg0 *big.Int) (bool, error) { - return _Bridge.Contract.ClaimNullifier(&_Bridge.CallOpts, arg0) -} - -// ClaimNullifier is a free data retrieval call binding the contract method 0xe7375881. -// -// Solidity: function claimNullifier(uint256 ) view returns(bool) -func (_Bridge *BridgeCallerSession) ClaimNullifier(arg0 *big.Int) (bool, error) { - return _Bridge.Contract.ClaimNullifier(&_Bridge.CallOpts, arg0) -} - -// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. -// -// Solidity: function depositCount() view returns(uint256) -func (_Bridge *BridgeCaller) DepositCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "depositCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. -// -// Solidity: function depositCount() view returns(uint256) -func (_Bridge *BridgeSession) DepositCount() (*big.Int, error) { - return _Bridge.Contract.DepositCount(&_Bridge.CallOpts) -} - -// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. -// -// Solidity: function depositCount() view returns(uint256) -func (_Bridge *BridgeCallerSession) DepositCount() (*big.Int, error) { - return _Bridge.Contract.DepositCount(&_Bridge.CallOpts) -} - -// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. -// -// Solidity: function getDepositRoot() view returns(bytes32) -func (_Bridge *BridgeCaller) GetDepositRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "getDepositRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. -// -// Solidity: function getDepositRoot() view returns(bytes32) -func (_Bridge *BridgeSession) GetDepositRoot() ([32]byte, error) { - return _Bridge.Contract.GetDepositRoot(&_Bridge.CallOpts) -} - -// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. -// -// Solidity: function getDepositRoot() view returns(bytes32) -func (_Bridge *BridgeCallerSession) GetDepositRoot() ([32]byte, error) { - return _Bridge.Contract.GetDepositRoot(&_Bridge.CallOpts) -} - -// GetLeafValue is a free data retrieval call binding the contract method 0x5a64a1da. -// -// Solidity: function getLeafValue(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) -func (_Bridge *BridgeCaller) GetLeafValue(opts *bind.CallOpts, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "getLeafValue", originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadataHash) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetLeafValue is a free data retrieval call binding the contract method 0x5a64a1da. -// -// Solidity: function getLeafValue(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) -func (_Bridge *BridgeSession) GetLeafValue(originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { - return _Bridge.Contract.GetLeafValue(&_Bridge.CallOpts, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadataHash) -} - -// GetLeafValue is a free data retrieval call binding the contract method 0x5a64a1da. -// -// Solidity: function getLeafValue(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) -func (_Bridge *BridgeCallerSession) GetLeafValue(originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { - return _Bridge.Contract.GetLeafValue(&_Bridge.CallOpts, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadataHash) -} - -// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. -// -// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeCaller) GetTokenWrappedAddress(opts *bind.CallOpts, originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "getTokenWrappedAddress", originNetwork, originTokenAddress) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. -// -// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeSession) GetTokenWrappedAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - return _Bridge.Contract.GetTokenWrappedAddress(&_Bridge.CallOpts, originNetwork, originTokenAddress) -} - -// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. -// -// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeCallerSession) GetTokenWrappedAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - return _Bridge.Contract.GetTokenWrappedAddress(&_Bridge.CallOpts, originNetwork, originTokenAddress) -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Bridge *BridgeCaller) GlobalExitRootManager(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "globalExitRootManager") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Bridge *BridgeSession) GlobalExitRootManager() (common.Address, error) { - return _Bridge.Contract.GlobalExitRootManager(&_Bridge.CallOpts) -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Bridge *BridgeCallerSession) GlobalExitRootManager() (common.Address, error) { - return _Bridge.Contract.GlobalExitRootManager(&_Bridge.CallOpts) -} - -// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. -// -// Solidity: function networkID() view returns(uint32) -func (_Bridge *BridgeCaller) NetworkID(opts *bind.CallOpts) (uint32, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "networkID") - - if err != nil { - return *new(uint32), err - } - - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) - - return out0, err - -} - -// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. -// -// Solidity: function networkID() view returns(uint32) -func (_Bridge *BridgeSession) NetworkID() (uint32, error) { - return _Bridge.Contract.NetworkID(&_Bridge.CallOpts) -} - -// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. -// -// Solidity: function networkID() view returns(uint32) -func (_Bridge *BridgeCallerSession) NetworkID() (uint32, error) { - return _Bridge.Contract.NetworkID(&_Bridge.CallOpts) -} - -// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xb7e6a7d4. -// -// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeCaller) PrecalculatedWrapperAddress(opts *bind.CallOpts, originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "precalculatedWrapperAddress", originNetwork, originTokenAddress) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xb7e6a7d4. -// -// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeSession) PrecalculatedWrapperAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - return _Bridge.Contract.PrecalculatedWrapperAddress(&_Bridge.CallOpts, originNetwork, originTokenAddress) -} - -// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xb7e6a7d4. -// -// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress) view returns(address) -func (_Bridge *BridgeCallerSession) PrecalculatedWrapperAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { - return _Bridge.Contract.PrecalculatedWrapperAddress(&_Bridge.CallOpts, originNetwork, originTokenAddress) -} - -// TokenImplementation is a free data retrieval call binding the contract method 0x2f3a3d5d. -// -// Solidity: function tokenImplementation() view returns(address) -func (_Bridge *BridgeCaller) TokenImplementation(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "tokenImplementation") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// TokenImplementation is a free data retrieval call binding the contract method 0x2f3a3d5d. -// -// Solidity: function tokenImplementation() view returns(address) -func (_Bridge *BridgeSession) TokenImplementation() (common.Address, error) { - return _Bridge.Contract.TokenImplementation(&_Bridge.CallOpts) -} - -// TokenImplementation is a free data retrieval call binding the contract method 0x2f3a3d5d. -// -// Solidity: function tokenImplementation() view returns(address) -func (_Bridge *BridgeCallerSession) TokenImplementation() (common.Address, error) { - return _Bridge.Contract.TokenImplementation(&_Bridge.CallOpts) -} - -// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. -// -// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) -func (_Bridge *BridgeCaller) TokenInfoToWrappedToken(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "tokenInfoToWrappedToken", arg0) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. -// -// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) -func (_Bridge *BridgeSession) TokenInfoToWrappedToken(arg0 [32]byte) (common.Address, error) { - return _Bridge.Contract.TokenInfoToWrappedToken(&_Bridge.CallOpts, arg0) -} - -// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. -// -// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) -func (_Bridge *BridgeCallerSession) TokenInfoToWrappedToken(arg0 [32]byte) (common.Address, error) { - return _Bridge.Contract.TokenInfoToWrappedToken(&_Bridge.CallOpts, arg0) -} - -// VerifyMerkleProof is a free data retrieval call binding the contract method 0x3da81682. -// -// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[] smtProof, uint64 index, bytes32 root) pure returns(bool) -func (_Bridge *BridgeCaller) VerifyMerkleProof(opts *bind.CallOpts, leafHash [32]byte, smtProof [][32]byte, index uint64, root [32]byte) (bool, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "verifyMerkleProof", leafHash, smtProof, index, root) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// VerifyMerkleProof is a free data retrieval call binding the contract method 0x3da81682. -// -// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[] smtProof, uint64 index, bytes32 root) pure returns(bool) -func (_Bridge *BridgeSession) VerifyMerkleProof(leafHash [32]byte, smtProof [][32]byte, index uint64, root [32]byte) (bool, error) { - return _Bridge.Contract.VerifyMerkleProof(&_Bridge.CallOpts, leafHash, smtProof, index, root) -} - -// VerifyMerkleProof is a free data retrieval call binding the contract method 0x3da81682. -// -// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[] smtProof, uint64 index, bytes32 root) pure returns(bool) -func (_Bridge *BridgeCallerSession) VerifyMerkleProof(leafHash [32]byte, smtProof [][32]byte, index uint64, root [32]byte) (bool, error) { - return _Bridge.Contract.VerifyMerkleProof(&_Bridge.CallOpts, leafHash, smtProof, index, root) -} - -// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. -// -// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) -func (_Bridge *BridgeCaller) WrappedTokenToTokenInfo(opts *bind.CallOpts, arg0 common.Address) (struct { - OriginNetwork uint32 - OriginTokenAddress common.Address -}, error) { - var out []interface{} - err := _Bridge.contract.Call(opts, &out, "wrappedTokenToTokenInfo", arg0) - - outstruct := new(struct { - OriginNetwork uint32 - OriginTokenAddress common.Address - }) - if err != nil { - return *outstruct, err - } - - outstruct.OriginNetwork = *abi.ConvertType(out[0], new(uint32)).(*uint32) - outstruct.OriginTokenAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) - - return *outstruct, err - -} - -// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. -// -// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) -func (_Bridge *BridgeSession) WrappedTokenToTokenInfo(arg0 common.Address) (struct { - OriginNetwork uint32 - OriginTokenAddress common.Address -}, error) { - return _Bridge.Contract.WrappedTokenToTokenInfo(&_Bridge.CallOpts, arg0) -} - -// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. -// -// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) -func (_Bridge *BridgeCallerSession) WrappedTokenToTokenInfo(arg0 common.Address) (struct { - OriginNetwork uint32 - OriginTokenAddress common.Address -}, error) { - return _Bridge.Contract.WrappedTokenToTokenInfo(&_Bridge.CallOpts, arg0) -} - -// Bridge is a paid mutator transaction binding the contract method 0x508935f8. -// -// Solidity: function bridge(address token, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes permitData) payable returns() -func (_Bridge *BridgeTransactor) Bridge(opts *bind.TransactOpts, token common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, permitData []byte) (*types.Transaction, error) { - return _Bridge.contract.Transact(opts, "bridge", token, destinationNetwork, destinationAddress, amount, permitData) -} - -// Bridge is a paid mutator transaction binding the contract method 0x508935f8. -// -// Solidity: function bridge(address token, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes permitData) payable returns() -func (_Bridge *BridgeSession) Bridge(token common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, permitData []byte) (*types.Transaction, error) { - return _Bridge.Contract.Bridge(&_Bridge.TransactOpts, token, destinationNetwork, destinationAddress, amount, permitData) -} - -// Bridge is a paid mutator transaction binding the contract method 0x508935f8. -// -// Solidity: function bridge(address token, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes permitData) payable returns() -func (_Bridge *BridgeTransactorSession) Bridge(token common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, permitData []byte) (*types.Transaction, error) { - return _Bridge.Contract.Bridge(&_Bridge.TransactOpts, token, destinationNetwork, destinationAddress, amount, permitData) -} - -// Claim is a paid mutator transaction binding the contract method 0x5d5d326f. -// -// Solidity: function claim(bytes32[] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() -func (_Bridge *BridgeTransactor) Claim(opts *bind.TransactOpts, smtProof [][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { - return _Bridge.contract.Transact(opts, "claim", smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) -} - -// Claim is a paid mutator transaction binding the contract method 0x5d5d326f. -// -// Solidity: function claim(bytes32[] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() -func (_Bridge *BridgeSession) Claim(smtProof [][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { - return _Bridge.Contract.Claim(&_Bridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) -} - -// Claim is a paid mutator transaction binding the contract method 0x5d5d326f. -// -// Solidity: function claim(bytes32[] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() -func (_Bridge *BridgeTransactorSession) Claim(smtProof [][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { - return _Bridge.Contract.Claim(&_Bridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) -} - -// Initialize is a paid mutator transaction binding the contract method 0x8624c35c. -// -// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager) returns() -func (_Bridge *BridgeTransactor) Initialize(opts *bind.TransactOpts, _networkID uint32, _globalExitRootManager common.Address) (*types.Transaction, error) { - return _Bridge.contract.Transact(opts, "initialize", _networkID, _globalExitRootManager) -} - -// Initialize is a paid mutator transaction binding the contract method 0x8624c35c. -// -// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager) returns() -func (_Bridge *BridgeSession) Initialize(_networkID uint32, _globalExitRootManager common.Address) (*types.Transaction, error) { - return _Bridge.Contract.Initialize(&_Bridge.TransactOpts, _networkID, _globalExitRootManager) -} - -// Initialize is a paid mutator transaction binding the contract method 0x8624c35c. -// -// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager) returns() -func (_Bridge *BridgeTransactorSession) Initialize(_networkID uint32, _globalExitRootManager common.Address) (*types.Transaction, error) { - return _Bridge.Contract.Initialize(&_Bridge.TransactOpts, _networkID, _globalExitRootManager) -} - -// BridgeBridgeEventIterator is returned from FilterBridgeEvent and is used to iterate over the raw logs and unpacked data for BridgeEvent events raised by the Bridge contract. -type BridgeBridgeEventIterator struct { - Event *BridgeBridgeEvent // 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 *BridgeBridgeEventIterator) 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(BridgeBridgeEvent) - 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(BridgeBridgeEvent) - 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 *BridgeBridgeEventIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BridgeBridgeEventIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BridgeBridgeEvent represents a BridgeEvent event raised by the Bridge contract. -type BridgeBridgeEvent struct { - OriginNetwork uint32 - OriginTokenAddress common.Address - DestinationNetwork uint32 - DestinationAddress common.Address - Amount *big.Int - Metadata []byte - DepositCount uint32 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBridgeEvent is a free log retrieval operation binding the contract event 0xf0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a. -// -// Solidity: event BridgeEvent(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) -func (_Bridge *BridgeFilterer) FilterBridgeEvent(opts *bind.FilterOpts) (*BridgeBridgeEventIterator, error) { - - logs, sub, err := _Bridge.contract.FilterLogs(opts, "BridgeEvent") - if err != nil { - return nil, err - } - return &BridgeBridgeEventIterator{contract: _Bridge.contract, event: "BridgeEvent", logs: logs, sub: sub}, nil -} - -// WatchBridgeEvent is a free log subscription operation binding the contract event 0xf0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a. -// -// Solidity: event BridgeEvent(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) -func (_Bridge *BridgeFilterer) WatchBridgeEvent(opts *bind.WatchOpts, sink chan<- *BridgeBridgeEvent) (event.Subscription, error) { - - logs, sub, err := _Bridge.contract.WatchLogs(opts, "BridgeEvent") - 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(BridgeBridgeEvent) - if err := _Bridge.contract.UnpackLog(event, "BridgeEvent", 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 -} - -// ParseBridgeEvent is a log parse operation binding the contract event 0xf0b963192bdc6349c23af9bd17294b4c7b9b5a73a2a9939610ea18ffd1c5dc2a. -// -// Solidity: event BridgeEvent(uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) -func (_Bridge *BridgeFilterer) ParseBridgeEvent(log types.Log) (*BridgeBridgeEvent, error) { - event := new(BridgeBridgeEvent) - if err := _Bridge.contract.UnpackLog(event, "BridgeEvent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BridgeClaimEventIterator is returned from FilterClaimEvent and is used to iterate over the raw logs and unpacked data for ClaimEvent events raised by the Bridge contract. -type BridgeClaimEventIterator struct { - Event *BridgeClaimEvent // 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 *BridgeClaimEventIterator) 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(BridgeClaimEvent) - 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(BridgeClaimEvent) - 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 *BridgeClaimEventIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BridgeClaimEventIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BridgeClaimEvent represents a ClaimEvent event raised by the Bridge contract. -type BridgeClaimEvent struct { - Index uint32 - OriginNetwork uint32 - OriginTokenAddress common.Address - DestinationAddress common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterClaimEvent is a free log retrieval operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. -// -// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originTokenAddress, address destinationAddress, uint256 amount) -func (_Bridge *BridgeFilterer) FilterClaimEvent(opts *bind.FilterOpts) (*BridgeClaimEventIterator, error) { - - logs, sub, err := _Bridge.contract.FilterLogs(opts, "ClaimEvent") - if err != nil { - return nil, err - } - return &BridgeClaimEventIterator{contract: _Bridge.contract, event: "ClaimEvent", logs: logs, sub: sub}, nil -} - -// WatchClaimEvent is a free log subscription operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. -// -// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originTokenAddress, address destinationAddress, uint256 amount) -func (_Bridge *BridgeFilterer) WatchClaimEvent(opts *bind.WatchOpts, sink chan<- *BridgeClaimEvent) (event.Subscription, error) { - - logs, sub, err := _Bridge.contract.WatchLogs(opts, "ClaimEvent") - 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(BridgeClaimEvent) - if err := _Bridge.contract.UnpackLog(event, "ClaimEvent", 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 -} - -// ParseClaimEvent is a log parse operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. -// -// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originTokenAddress, address destinationAddress, uint256 amount) -func (_Bridge *BridgeFilterer) ParseClaimEvent(log types.Log) (*BridgeClaimEvent, error) { - event := new(BridgeClaimEvent) - if err := _Bridge.contract.UnpackLog(event, "ClaimEvent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BridgeInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Bridge contract. -type BridgeInitializedIterator struct { - Event *BridgeInitialized // 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 *BridgeInitializedIterator) 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(BridgeInitialized) - 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(BridgeInitialized) - 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 *BridgeInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BridgeInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BridgeInitialized represents a Initialized event raised by the Bridge contract. -type BridgeInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Bridge *BridgeFilterer) FilterInitialized(opts *bind.FilterOpts) (*BridgeInitializedIterator, error) { - - logs, sub, err := _Bridge.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &BridgeInitializedIterator{contract: _Bridge.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Bridge *BridgeFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *BridgeInitialized) (event.Subscription, error) { - - logs, sub, err := _Bridge.contract.WatchLogs(opts, "Initialized") - 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(BridgeInitialized) - if err := _Bridge.contract.UnpackLog(event, "Initialized", 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 -} - -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Bridge *BridgeFilterer) ParseInitialized(log types.Log) (*BridgeInitialized, error) { - event := new(BridgeInitialized) - if err := _Bridge.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BridgeNewWrappedTokenIterator is returned from FilterNewWrappedToken and is used to iterate over the raw logs and unpacked data for NewWrappedToken events raised by the Bridge contract. -type BridgeNewWrappedTokenIterator struct { - Event *BridgeNewWrappedToken // 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 *BridgeNewWrappedTokenIterator) 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(BridgeNewWrappedToken) - 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(BridgeNewWrappedToken) - 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 *BridgeNewWrappedTokenIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BridgeNewWrappedTokenIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BridgeNewWrappedToken represents a NewWrappedToken event raised by the Bridge contract. -type BridgeNewWrappedToken struct { - OriginNetwork uint32 - OriginTokenAddress common.Address - WrappedTokenAddress common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterNewWrappedToken is a free log retrieval operation binding the contract event 0xccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d59. -// -// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress) -func (_Bridge *BridgeFilterer) FilterNewWrappedToken(opts *bind.FilterOpts) (*BridgeNewWrappedTokenIterator, error) { - - logs, sub, err := _Bridge.contract.FilterLogs(opts, "NewWrappedToken") - if err != nil { - return nil, err - } - return &BridgeNewWrappedTokenIterator{contract: _Bridge.contract, event: "NewWrappedToken", logs: logs, sub: sub}, nil -} - -// WatchNewWrappedToken is a free log subscription operation binding the contract event 0xccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d59. -// -// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress) -func (_Bridge *BridgeFilterer) WatchNewWrappedToken(opts *bind.WatchOpts, sink chan<- *BridgeNewWrappedToken) (event.Subscription, error) { - - logs, sub, err := _Bridge.contract.WatchLogs(opts, "NewWrappedToken") - 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(BridgeNewWrappedToken) - if err := _Bridge.contract.UnpackLog(event, "NewWrappedToken", 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 -} - -// ParseNewWrappedToken is a log parse operation binding the contract event 0xccd7715648d1f2bb13e158f96b5b6c3aeda555d4cb87112e274a6f28bc571d59. -// -// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress) -func (_Bridge *BridgeFilterer) ParseNewWrappedToken(log types.Log) (*BridgeNewWrappedToken, error) { - event := new(BridgeNewWrappedToken) - if err := _Bridge.contract.UnpackLog(event, "NewWrappedToken", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/etherman/smartcontracts/globalexitrootmanager/globalexitrootmanager.go b/etherman/smartcontracts/globalexitrootmanager/globalexitrootmanager.go deleted file mode 100644 index 44387a6138..0000000000 --- a/etherman/smartcontracts/globalexitrootmanager/globalexitrootmanager.go +++ /dev/null @@ -1,757 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package globalexitrootmanager - -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 -) - -// GlobalexitrootmanagerMetaData contains all meta data concerning the Globalexitrootmanager contract. -var GlobalexitrootmanagerMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"globalExitRootNum\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"mainnetExitRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"rollupExitRoot\",\"type\":\"bytes32\"}],\"name\":\"UpdateGlobalExitRoot\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"bridgeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastGlobalExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"globalExitRootMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rollupAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bridgeAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastGlobalExitRootNum\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMainnetExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRollupExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"newRoot\",\"type\":\"bytes32\"}],\"name\":\"updateExitRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061066c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c806333d6247d11610076578063485cc9551161005b578063485cc955146101445780635ec6a8df14610157578063a3c573eb1461019c57600080fd5b806333d6247d146100f65780633ed691ef1461010b57600080fd5b806301fd9044146100a8578063029f2793146100c4578063257b3632146100cd578063319cf735146100ed575b600080fd5b6100b160015481565b6040519081526020015b60405180910390f35b6100b160045481565b6100b16100db366004610562565b60036020526000908152604090205481565b6100b160025481565b610109610104366004610562565b6101bc565b005b6100b160025460015460408051602081019390935282015260009060600160405160208183030381529060405280519060200120905090565b6101096101523660046105a4565b610381565b6006546101779073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bb565b6005546101779073ffffffffffffffffffffffffffffffffffffffff1681565b60065473ffffffffffffffffffffffffffffffffffffffff163314806101f9575060055473ffffffffffffffffffffffffffffffffffffffff1633145b61028a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f476c6f62616c45786974526f6f744d616e616765723a3a75706461746545786960448201527f74526f6f743a204f4e4c595f414c4c4f5745445f434f4e54524143545300000060648201526084015b60405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff1633036102af5760018190555b60055473ffffffffffffffffffffffffffffffffffffffff1633036102d45760028190555b600480549060006102e4836105d7565b9091555050600254600154604080516020810193909352820152600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060045460008281526003909352928220839055600154600254919550939092917fb7c409af8cb511116b88f38824d48a0196194596241fdb2d177210d3d3b89fbf91a45050565b600054610100900460ff16158080156103a15750600054600160ff909116105b806103bb5750303b1580156103bb575060005460ff166001145b610447576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610281565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156104a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6006805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556005805492851692909116919091179055801561055d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006020828403121561057457600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461059f57600080fd5b919050565b600080604083850312156105b757600080fd5b6105c08361057b565b91506105ce6020840161057b565b90509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361062f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea2646970667358221220d9ccfdddba433da7a9a14980d28db4b102be77f8af6cb74001850e88e278061864736f6c634300080f0033", -} - -// GlobalexitrootmanagerABI is the input ABI used to generate the binding from. -// Deprecated: Use GlobalexitrootmanagerMetaData.ABI instead. -var GlobalexitrootmanagerABI = GlobalexitrootmanagerMetaData.ABI - -// GlobalexitrootmanagerBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use GlobalexitrootmanagerMetaData.Bin instead. -var GlobalexitrootmanagerBin = GlobalexitrootmanagerMetaData.Bin - -// DeployGlobalexitrootmanager deploys a new Ethereum contract, binding an instance of Globalexitrootmanager to it. -func DeployGlobalexitrootmanager(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Globalexitrootmanager, error) { - parsed, err := GlobalexitrootmanagerMetaData.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(GlobalexitrootmanagerBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Globalexitrootmanager{GlobalexitrootmanagerCaller: GlobalexitrootmanagerCaller{contract: contract}, GlobalexitrootmanagerTransactor: GlobalexitrootmanagerTransactor{contract: contract}, GlobalexitrootmanagerFilterer: GlobalexitrootmanagerFilterer{contract: contract}}, nil -} - -// Globalexitrootmanager is an auto generated Go binding around an Ethereum contract. -type Globalexitrootmanager struct { - GlobalexitrootmanagerCaller // Read-only binding to the contract - GlobalexitrootmanagerTransactor // Write-only binding to the contract - GlobalexitrootmanagerFilterer // Log filterer for contract events -} - -// GlobalexitrootmanagerCaller is an auto generated read-only Go binding around an Ethereum contract. -type GlobalexitrootmanagerCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// GlobalexitrootmanagerTransactor is an auto generated write-only Go binding around an Ethereum contract. -type GlobalexitrootmanagerTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// GlobalexitrootmanagerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type GlobalexitrootmanagerFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// GlobalexitrootmanagerSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type GlobalexitrootmanagerSession struct { - Contract *Globalexitrootmanager // 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 -} - -// GlobalexitrootmanagerCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type GlobalexitrootmanagerCallerSession struct { - Contract *GlobalexitrootmanagerCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// GlobalexitrootmanagerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type GlobalexitrootmanagerTransactorSession struct { - Contract *GlobalexitrootmanagerTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// GlobalexitrootmanagerRaw is an auto generated low-level Go binding around an Ethereum contract. -type GlobalexitrootmanagerRaw struct { - Contract *Globalexitrootmanager // Generic contract binding to access the raw methods on -} - -// GlobalexitrootmanagerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type GlobalexitrootmanagerCallerRaw struct { - Contract *GlobalexitrootmanagerCaller // Generic read-only contract binding to access the raw methods on -} - -// GlobalexitrootmanagerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type GlobalexitrootmanagerTransactorRaw struct { - Contract *GlobalexitrootmanagerTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewGlobalexitrootmanager creates a new instance of Globalexitrootmanager, bound to a specific deployed contract. -func NewGlobalexitrootmanager(address common.Address, backend bind.ContractBackend) (*Globalexitrootmanager, error) { - contract, err := bindGlobalexitrootmanager(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Globalexitrootmanager{GlobalexitrootmanagerCaller: GlobalexitrootmanagerCaller{contract: contract}, GlobalexitrootmanagerTransactor: GlobalexitrootmanagerTransactor{contract: contract}, GlobalexitrootmanagerFilterer: GlobalexitrootmanagerFilterer{contract: contract}}, nil -} - -// NewGlobalexitrootmanagerCaller creates a new read-only instance of Globalexitrootmanager, bound to a specific deployed contract. -func NewGlobalexitrootmanagerCaller(address common.Address, caller bind.ContractCaller) (*GlobalexitrootmanagerCaller, error) { - contract, err := bindGlobalexitrootmanager(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &GlobalexitrootmanagerCaller{contract: contract}, nil -} - -// NewGlobalexitrootmanagerTransactor creates a new write-only instance of Globalexitrootmanager, bound to a specific deployed contract. -func NewGlobalexitrootmanagerTransactor(address common.Address, transactor bind.ContractTransactor) (*GlobalexitrootmanagerTransactor, error) { - contract, err := bindGlobalexitrootmanager(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &GlobalexitrootmanagerTransactor{contract: contract}, nil -} - -// NewGlobalexitrootmanagerFilterer creates a new log filterer instance of Globalexitrootmanager, bound to a specific deployed contract. -func NewGlobalexitrootmanagerFilterer(address common.Address, filterer bind.ContractFilterer) (*GlobalexitrootmanagerFilterer, error) { - contract, err := bindGlobalexitrootmanager(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &GlobalexitrootmanagerFilterer{contract: contract}, nil -} - -// bindGlobalexitrootmanager binds a generic wrapper to an already deployed contract. -func bindGlobalexitrootmanager(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(GlobalexitrootmanagerABI)) - 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 (_Globalexitrootmanager *GlobalexitrootmanagerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Globalexitrootmanager.Contract.GlobalexitrootmanagerCaller.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 (_Globalexitrootmanager *GlobalexitrootmanagerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.GlobalexitrootmanagerTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Globalexitrootmanager *GlobalexitrootmanagerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.GlobalexitrootmanagerTransactor.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 (_Globalexitrootmanager *GlobalexitrootmanagerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Globalexitrootmanager.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 (_Globalexitrootmanager *GlobalexitrootmanagerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Globalexitrootmanager *GlobalexitrootmanagerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.contract.Transact(opts, method, params...) -} - -// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. -// -// Solidity: function bridgeAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) BridgeAddress(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "bridgeAddress") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. -// -// Solidity: function bridgeAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) BridgeAddress() (common.Address, error) { - return _Globalexitrootmanager.Contract.BridgeAddress(&_Globalexitrootmanager.CallOpts) -} - -// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. -// -// Solidity: function bridgeAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) BridgeAddress() (common.Address, error) { - return _Globalexitrootmanager.Contract.BridgeAddress(&_Globalexitrootmanager.CallOpts) -} - -// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. -// -// Solidity: function getLastGlobalExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) GetLastGlobalExitRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "getLastGlobalExitRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. -// -// Solidity: function getLastGlobalExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) GetLastGlobalExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.GetLastGlobalExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. -// -// Solidity: function getLastGlobalExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) GetLastGlobalExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.GetLastGlobalExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. -// -// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) GlobalExitRootMap(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "globalExitRootMap", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. -// -// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) GlobalExitRootMap(arg0 [32]byte) (*big.Int, error) { - return _Globalexitrootmanager.Contract.GlobalExitRootMap(&_Globalexitrootmanager.CallOpts, arg0) -} - -// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. -// -// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) GlobalExitRootMap(arg0 [32]byte) (*big.Int, error) { - return _Globalexitrootmanager.Contract.GlobalExitRootMap(&_Globalexitrootmanager.CallOpts, arg0) -} - -// LastGlobalExitRootNum is a free data retrieval call binding the contract method 0x029f2793. -// -// Solidity: function lastGlobalExitRootNum() view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) LastGlobalExitRootNum(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "lastGlobalExitRootNum") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// LastGlobalExitRootNum is a free data retrieval call binding the contract method 0x029f2793. -// -// Solidity: function lastGlobalExitRootNum() view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) LastGlobalExitRootNum() (*big.Int, error) { - return _Globalexitrootmanager.Contract.LastGlobalExitRootNum(&_Globalexitrootmanager.CallOpts) -} - -// LastGlobalExitRootNum is a free data retrieval call binding the contract method 0x029f2793. -// -// Solidity: function lastGlobalExitRootNum() view returns(uint256) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) LastGlobalExitRootNum() (*big.Int, error) { - return _Globalexitrootmanager.Contract.LastGlobalExitRootNum(&_Globalexitrootmanager.CallOpts) -} - -// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. -// -// Solidity: function lastMainnetExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) LastMainnetExitRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "lastMainnetExitRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. -// -// Solidity: function lastMainnetExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) LastMainnetExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.LastMainnetExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. -// -// Solidity: function lastMainnetExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) LastMainnetExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.LastMainnetExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. -// -// Solidity: function lastRollupExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) LastRollupExitRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "lastRollupExitRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. -// -// Solidity: function lastRollupExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) LastRollupExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.LastRollupExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. -// -// Solidity: function lastRollupExitRoot() view returns(bytes32) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) LastRollupExitRoot() ([32]byte, error) { - return _Globalexitrootmanager.Contract.LastRollupExitRoot(&_Globalexitrootmanager.CallOpts) -} - -// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. -// -// Solidity: function rollupAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerCaller) RollupAddress(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Globalexitrootmanager.contract.Call(opts, &out, "rollupAddress") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. -// -// Solidity: function rollupAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) RollupAddress() (common.Address, error) { - return _Globalexitrootmanager.Contract.RollupAddress(&_Globalexitrootmanager.CallOpts) -} - -// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. -// -// Solidity: function rollupAddress() view returns(address) -func (_Globalexitrootmanager *GlobalexitrootmanagerCallerSession) RollupAddress() (common.Address, error) { - return _Globalexitrootmanager.Contract.RollupAddress(&_Globalexitrootmanager.CallOpts) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _rollupAddress, address _bridgeAddress) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerTransactor) Initialize(opts *bind.TransactOpts, _rollupAddress common.Address, _bridgeAddress common.Address) (*types.Transaction, error) { - return _Globalexitrootmanager.contract.Transact(opts, "initialize", _rollupAddress, _bridgeAddress) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _rollupAddress, address _bridgeAddress) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) Initialize(_rollupAddress common.Address, _bridgeAddress common.Address) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.Initialize(&_Globalexitrootmanager.TransactOpts, _rollupAddress, _bridgeAddress) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _rollupAddress, address _bridgeAddress) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerTransactorSession) Initialize(_rollupAddress common.Address, _bridgeAddress common.Address) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.Initialize(&_Globalexitrootmanager.TransactOpts, _rollupAddress, _bridgeAddress) -} - -// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. -// -// Solidity: function updateExitRoot(bytes32 newRoot) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerTransactor) UpdateExitRoot(opts *bind.TransactOpts, newRoot [32]byte) (*types.Transaction, error) { - return _Globalexitrootmanager.contract.Transact(opts, "updateExitRoot", newRoot) -} - -// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. -// -// Solidity: function updateExitRoot(bytes32 newRoot) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerSession) UpdateExitRoot(newRoot [32]byte) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.UpdateExitRoot(&_Globalexitrootmanager.TransactOpts, newRoot) -} - -// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. -// -// Solidity: function updateExitRoot(bytes32 newRoot) returns() -func (_Globalexitrootmanager *GlobalexitrootmanagerTransactorSession) UpdateExitRoot(newRoot [32]byte) (*types.Transaction, error) { - return _Globalexitrootmanager.Contract.UpdateExitRoot(&_Globalexitrootmanager.TransactOpts, newRoot) -} - -// GlobalexitrootmanagerInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Globalexitrootmanager contract. -type GlobalexitrootmanagerInitializedIterator struct { - Event *GlobalexitrootmanagerInitialized // 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 *GlobalexitrootmanagerInitializedIterator) 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(GlobalexitrootmanagerInitialized) - 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(GlobalexitrootmanagerInitialized) - 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 *GlobalexitrootmanagerInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *GlobalexitrootmanagerInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// GlobalexitrootmanagerInitialized represents a Initialized event raised by the Globalexitrootmanager contract. -type GlobalexitrootmanagerInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) FilterInitialized(opts *bind.FilterOpts) (*GlobalexitrootmanagerInitializedIterator, error) { - - logs, sub, err := _Globalexitrootmanager.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &GlobalexitrootmanagerInitializedIterator{contract: _Globalexitrootmanager.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *GlobalexitrootmanagerInitialized) (event.Subscription, error) { - - logs, sub, err := _Globalexitrootmanager.contract.WatchLogs(opts, "Initialized") - 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(GlobalexitrootmanagerInitialized) - if err := _Globalexitrootmanager.contract.UnpackLog(event, "Initialized", 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 -} - -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) ParseInitialized(log types.Log) (*GlobalexitrootmanagerInitialized, error) { - event := new(GlobalexitrootmanagerInitialized) - if err := _Globalexitrootmanager.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// GlobalexitrootmanagerUpdateGlobalExitRootIterator is returned from FilterUpdateGlobalExitRoot and is used to iterate over the raw logs and unpacked data for UpdateGlobalExitRoot events raised by the Globalexitrootmanager contract. -type GlobalexitrootmanagerUpdateGlobalExitRootIterator struct { - Event *GlobalexitrootmanagerUpdateGlobalExitRoot // 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 *GlobalexitrootmanagerUpdateGlobalExitRootIterator) 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(GlobalexitrootmanagerUpdateGlobalExitRoot) - 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(GlobalexitrootmanagerUpdateGlobalExitRoot) - 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 *GlobalexitrootmanagerUpdateGlobalExitRootIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *GlobalexitrootmanagerUpdateGlobalExitRootIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// GlobalexitrootmanagerUpdateGlobalExitRoot represents a UpdateGlobalExitRoot event raised by the Globalexitrootmanager contract. -type GlobalexitrootmanagerUpdateGlobalExitRoot struct { - GlobalExitRootNum *big.Int - MainnetExitRoot [32]byte - RollupExitRoot [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterUpdateGlobalExitRoot is a free log retrieval operation binding the contract event 0xb7c409af8cb511116b88f38824d48a0196194596241fdb2d177210d3d3b89fbf. -// -// Solidity: event UpdateGlobalExitRoot(uint256 indexed globalExitRootNum, bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) FilterUpdateGlobalExitRoot(opts *bind.FilterOpts, globalExitRootNum []*big.Int, mainnetExitRoot [][32]byte, rollupExitRoot [][32]byte) (*GlobalexitrootmanagerUpdateGlobalExitRootIterator, error) { - - var globalExitRootNumRule []interface{} - for _, globalExitRootNumItem := range globalExitRootNum { - globalExitRootNumRule = append(globalExitRootNumRule, globalExitRootNumItem) - } - var mainnetExitRootRule []interface{} - for _, mainnetExitRootItem := range mainnetExitRoot { - mainnetExitRootRule = append(mainnetExitRootRule, mainnetExitRootItem) - } - var rollupExitRootRule []interface{} - for _, rollupExitRootItem := range rollupExitRoot { - rollupExitRootRule = append(rollupExitRootRule, rollupExitRootItem) - } - - logs, sub, err := _Globalexitrootmanager.contract.FilterLogs(opts, "UpdateGlobalExitRoot", globalExitRootNumRule, mainnetExitRootRule, rollupExitRootRule) - if err != nil { - return nil, err - } - return &GlobalexitrootmanagerUpdateGlobalExitRootIterator{contract: _Globalexitrootmanager.contract, event: "UpdateGlobalExitRoot", logs: logs, sub: sub}, nil -} - -// WatchUpdateGlobalExitRoot is a free log subscription operation binding the contract event 0xb7c409af8cb511116b88f38824d48a0196194596241fdb2d177210d3d3b89fbf. -// -// Solidity: event UpdateGlobalExitRoot(uint256 indexed globalExitRootNum, bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) WatchUpdateGlobalExitRoot(opts *bind.WatchOpts, sink chan<- *GlobalexitrootmanagerUpdateGlobalExitRoot, globalExitRootNum []*big.Int, mainnetExitRoot [][32]byte, rollupExitRoot [][32]byte) (event.Subscription, error) { - - var globalExitRootNumRule []interface{} - for _, globalExitRootNumItem := range globalExitRootNum { - globalExitRootNumRule = append(globalExitRootNumRule, globalExitRootNumItem) - } - var mainnetExitRootRule []interface{} - for _, mainnetExitRootItem := range mainnetExitRoot { - mainnetExitRootRule = append(mainnetExitRootRule, mainnetExitRootItem) - } - var rollupExitRootRule []interface{} - for _, rollupExitRootItem := range rollupExitRoot { - rollupExitRootRule = append(rollupExitRootRule, rollupExitRootItem) - } - - logs, sub, err := _Globalexitrootmanager.contract.WatchLogs(opts, "UpdateGlobalExitRoot", globalExitRootNumRule, mainnetExitRootRule, rollupExitRootRule) - 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(GlobalexitrootmanagerUpdateGlobalExitRoot) - if err := _Globalexitrootmanager.contract.UnpackLog(event, "UpdateGlobalExitRoot", 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 -} - -// ParseUpdateGlobalExitRoot is a log parse operation binding the contract event 0xb7c409af8cb511116b88f38824d48a0196194596241fdb2d177210d3d3b89fbf. -// -// Solidity: event UpdateGlobalExitRoot(uint256 indexed globalExitRootNum, bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) -func (_Globalexitrootmanager *GlobalexitrootmanagerFilterer) ParseUpdateGlobalExitRoot(log types.Log) (*GlobalexitrootmanagerUpdateGlobalExitRoot, error) { - event := new(GlobalexitrootmanagerUpdateGlobalExitRoot) - if err := _Globalexitrootmanager.contract.UnpackLog(event, "UpdateGlobalExitRoot", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/etherman/smartcontracts/matic/matic.go b/etherman/smartcontracts/matic/matic.go index 38836a1e7e..d721b36431 100644 --- a/etherman/smartcontracts/matic/matic.go +++ b/etherman/smartcontracts/matic/matic.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // MaticMetaData contains all meta data concerning the Matic contract. @@ -156,11 +157,11 @@ func NewMaticFilterer(address common.Address, filterer bind.ContractFilterer) (* // bindMatic binds a generic wrapper to an already deployed contract. func bindMatic(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(MaticABI)) + parsed, err := MaticMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/etherman/smartcontracts/mockverifier/mockverifier.go b/etherman/smartcontracts/mockverifier/mockverifier.go index 609ccba6ca..d7038e7354 100644 --- a/etherman/smartcontracts/mockverifier/mockverifier.go +++ b/etherman/smartcontracts/mockverifier/mockverifier.go @@ -26,12 +26,13 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // MockverifierMetaData contains all meta data concerning the Mockverifier contract. var MockverifierMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"a\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2][2]\",\"name\":\"b\",\"type\":\"uint256[2][2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"c\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[1]\",\"name\":\"input\",\"type\":\"uint256[1]\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610101806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806343753b4d14602d575b600080fd5b60426038366004606c565b6001949350505050565b604051901515815260200160405180910390f35b8060408101831015606657600080fd5b92915050565b600080600080610120808688031215608357600080fd5b608b87876056565b945060c0860187811115609d57600080fd5b60408701945060ab88826056565b93505086818701111560bc57600080fd5b5092959194509261010001915056fea2646970667358221220569286c06a35bb3b6e29da343de6015d1fc7ba685f6b59f888f00e18129e37df64736f6c634300080f0033", + ABI: "[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"uint256[1]\",\"name\":\"pubSignals\",\"type\":\"uint256[1]\"}],\"name\":\"verifyProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610205806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80638d8f8a5c14610030575b600080fd5b61004661003e366004610128565b600192915050565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156100b2576100b261005a565b604052919050565b600082601f8301126100cb57600080fd5b604051602080820182811067ffffffffffffffff821117156100ef576100ef61005a565b604052818482018681111561010357600080fd5b855b8181101561011c5780358352918301918301610105565b50929695505050505050565b6000806040838503121561013b57600080fd5b823567ffffffffffffffff8082111561015357600080fd5b818501915085601f83011261016757600080fd5b813560208282111561017b5761017b61005a565b61018d601f8301601f19168201610089565b925081835287818386010111156101a357600080fd5b818185018285013760008183850101528295506101c2888289016100ba565b945050505050925092905056fea26469706673582212204af7f3bda67f3a30e1891af134e290590c6063b5a163b85e57b0c1111e1463a364736f6c63430008110033", } // MockverifierABI is the input ABI used to generate the binding from. @@ -156,11 +157,11 @@ func NewMockverifierFilterer(address common.Address, filterer bind.ContractFilte // bindMockverifier binds a generic wrapper to an already deployed contract. func bindMockverifier(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(MockverifierABI)) + parsed, err := MockverifierMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and @@ -201,12 +202,12 @@ func (_Mockverifier *MockverifierTransactorRaw) Transact(opts *bind.TransactOpts return _Mockverifier.Contract.contract.Transact(opts, method, params...) } -// VerifyProof is a free data retrieval call binding the contract method 0x43753b4d. +// VerifyProof is a free data retrieval call binding the contract method 0x8d8f8a5c. // -// Solidity: function verifyProof(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[1] input) view returns(bool) -func (_Mockverifier *MockverifierCaller) VerifyProof(opts *bind.CallOpts, a [2]*big.Int, b [2][2]*big.Int, c [2]*big.Int, input [1]*big.Int) (bool, error) { +// Solidity: function verifyProof(bytes proof, uint256[1] pubSignals) view returns(bool) +func (_Mockverifier *MockverifierCaller) VerifyProof(opts *bind.CallOpts, proof []byte, pubSignals [1]*big.Int) (bool, error) { var out []interface{} - err := _Mockverifier.contract.Call(opts, &out, "verifyProof", a, b, c, input) + err := _Mockverifier.contract.Call(opts, &out, "verifyProof", proof, pubSignals) if err != nil { return *new(bool), err @@ -218,16 +219,16 @@ func (_Mockverifier *MockverifierCaller) VerifyProof(opts *bind.CallOpts, a [2]* } -// VerifyProof is a free data retrieval call binding the contract method 0x43753b4d. +// VerifyProof is a free data retrieval call binding the contract method 0x8d8f8a5c. // -// Solidity: function verifyProof(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[1] input) view returns(bool) -func (_Mockverifier *MockverifierSession) VerifyProof(a [2]*big.Int, b [2][2]*big.Int, c [2]*big.Int, input [1]*big.Int) (bool, error) { - return _Mockverifier.Contract.VerifyProof(&_Mockverifier.CallOpts, a, b, c, input) +// Solidity: function verifyProof(bytes proof, uint256[1] pubSignals) view returns(bool) +func (_Mockverifier *MockverifierSession) VerifyProof(proof []byte, pubSignals [1]*big.Int) (bool, error) { + return _Mockverifier.Contract.VerifyProof(&_Mockverifier.CallOpts, proof, pubSignals) } -// VerifyProof is a free data retrieval call binding the contract method 0x43753b4d. +// VerifyProof is a free data retrieval call binding the contract method 0x8d8f8a5c. // -// Solidity: function verifyProof(uint256[2] a, uint256[2][2] b, uint256[2] c, uint256[1] input) view returns(bool) -func (_Mockverifier *MockverifierCallerSession) VerifyProof(a [2]*big.Int, b [2][2]*big.Int, c [2]*big.Int, input [1]*big.Int) (bool, error) { - return _Mockverifier.Contract.VerifyProof(&_Mockverifier.CallOpts, a, b, c, input) +// Solidity: function verifyProof(bytes proof, uint256[1] pubSignals) view returns(bool) +func (_Mockverifier *MockverifierCallerSession) VerifyProof(proof []byte, pubSignals [1]*big.Int) (bool, error) { + return _Mockverifier.Contract.VerifyProof(&_Mockverifier.CallOpts, proof, pubSignals) } diff --git a/etherman/smartcontracts/polygonzkevm/polygonzkevm.go b/etherman/smartcontracts/polygonzkevm/polygonzkevm.go new file mode 100644 index 0000000000..525612a194 --- /dev/null +++ b/etherman/smartcontracts/polygonzkevm/polygonzkevm.go @@ -0,0 +1,5308 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package polygonzkevm + +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 + _ = abi.ConvertType +) + +// PolygonZkEVMBatchData is an auto generated low-level Go binding around an user-defined struct. +type PolygonZkEVMBatchData struct { + Transactions []byte + GlobalExitRoot [32]byte + Timestamp uint64 + MinForcedTimestamp uint64 +} + +// PolygonZkEVMForcedBatchData is an auto generated low-level Go binding around an user-defined struct. +type PolygonZkEVMForcedBatchData struct { + Transactions []byte + GlobalExitRoot [32]byte + MinForcedTimestamp uint64 +} + +// PolygonZkEVMInitializePackedParameters is an auto generated low-level Go binding around an user-defined struct. +type PolygonZkEVMInitializePackedParameters struct { + Admin common.Address + TrustedSequencer common.Address + PendingStateTimeout uint64 + TrustedAggregator common.Address + TrustedAggregatorTimeout uint64 +} + +// PolygonzkevmMetaData contains all meta data concerning the Polygonzkevm contract. +var PolygonzkevmMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractIPolygonZkEVMGlobalExitRoot\",\"name\":\"_globalExitRootManager\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Upgradeable\",\"name\":\"_matic\",\"type\":\"address\"},{\"internalType\":\"contractIVerifierRollup\",\"name\":\"_rollupVerifier\",\"type\":\"address\"},{\"internalType\":\"contractIPolygonZkEVMBridge\",\"name\":\"_bridgeAddress\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_chainID\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_forkID\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BatchAlreadyVerified\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BatchNotSequencedOrNotSequenceEnd\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExceedMaxVerifyBatches\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FinalNumBatchBelowLastVerifiedBatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FinalNumBatchDoesNotMatchPendingState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FinalPendingStateNumInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForceBatchNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForceBatchTimeoutNotExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForceBatchesAlreadyActive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForceBatchesOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ForcedDataDoesNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GlobalExitRootNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HaltTimeoutNotExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitNumBatchAboveLastVerifiedBatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitNumBatchDoesNotMatchPendingState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRangeBatchTimeTarget\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRangeForceBatchTimeout\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRangeMultiplierBatchFee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewAccInputHashDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewPendingStateTimeoutMustBeLower\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewStateRootNotInsidePrime\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewTrustedAggregatorTimeoutMustBeLower\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughMaticAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldAccInputHashDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OldStateRootDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyEmergencyState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyNotEmergencyState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPendingAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyTrustedAggregator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyTrustedSequencer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingStateDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingStateInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingStateNotConsolidable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingStateTimeoutExceedHaltAggregationTimeout\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SequenceZeroBatches\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SequencedTimestampBelowForcedTimestamp\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SequencedTimestampInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StoredRootMustBeDifferentThanNewRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransactionsLengthAboveMax\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TrustedAggregatorTimeoutExceedHaltAggregationTimeout\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TrustedAggregatorTimeoutNotExpired\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AcceptAdminRole\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ActivateForceBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"pendingStateNum\",\"type\":\"uint64\"}],\"name\":\"ConsolidatePendingState\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EmergencyStateActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EmergencyStateDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"forceBatchNum\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"lastGlobalExitRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"}],\"name\":\"ForceBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"OverridePendingState\",\"type\":\"event\"},{\"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\":false,\"internalType\":\"bytes32\",\"name\":\"storedStateRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"provedStateRoot\",\"type\":\"bytes32\"}],\"name\":\"ProveNonDeterministicPendingState\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"}],\"name\":\"SequenceBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"}],\"name\":\"SequenceForceBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newforceBatchTimeout\",\"type\":\"uint64\"}],\"name\":\"SetForceBatchTimeout\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"newMultiplierBatchFee\",\"type\":\"uint16\"}],\"name\":\"SetMultiplierBatchFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newPendingStateTimeout\",\"type\":\"uint64\"}],\"name\":\"SetPendingStateTimeout\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTrustedAggregator\",\"type\":\"address\"}],\"name\":\"SetTrustedAggregator\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newTrustedAggregatorTimeout\",\"type\":\"uint64\"}],\"name\":\"SetTrustedAggregatorTimeout\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTrustedSequencer\",\"type\":\"address\"}],\"name\":\"SetTrustedSequencer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newTrustedSequencerURL\",\"type\":\"string\"}],\"name\":\"SetTrustedSequencerURL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVerifyBatchTimeTarget\",\"type\":\"uint64\"}],\"name\":\"SetVerifyBatchTimeTarget\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"TransferAdminRole\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"forkID\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"UpdateZkEVMVersion\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"VerifyBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"VerifyBatchesTrustedAggregator\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptAdminRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sequencedBatchNum\",\"type\":\"uint64\"}],\"name\":\"activateEmergencyState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"activateForceBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"batchNumToStateRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bridgeAddress\",\"outputs\":[{\"internalType\":\"contractIPolygonZkEVMBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculateRewardPerBatch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainID\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newStateRoot\",\"type\":\"uint256\"}],\"name\":\"checkStateRootInsidePrime\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"pendingStateNum\",\"type\":\"uint64\"}],\"name\":\"consolidatePendingState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deactivateEmergencyState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maticAmount\",\"type\":\"uint256\"}],\"name\":\"forceBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"forceBatchTimeout\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"forcedBatches\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"forkID\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getForcedBatchFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"initNumBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalNewBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"oldStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"}],\"name\":\"getInputSnarkBytes\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastVerifiedBatch\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalExitRootManager\",\"outputs\":[{\"internalType\":\"contractIPolygonZkEVMGlobalExitRoot\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"trustedSequencer\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"pendingStateTimeout\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"trustedAggregator\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"trustedAggregatorTimeout\",\"type\":\"uint64\"}],\"internalType\":\"structPolygonZkEVM.InitializePackedParameters\",\"name\":\"initializePackedParameters\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"genesisRoot\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_trustedSequencerURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_networkName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_version\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isEmergencyState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isForcedBatchDisallowed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"pendingStateNum\",\"type\":\"uint64\"}],\"name\":\"isPendingStateConsolidable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchSequenced\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastForceBatch\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastForceBatchSequenced\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPendingState\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPendingStateConsolidated\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastVerifiedBatch\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"matic\",\"outputs\":[{\"internalType\":\"contractIERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"multiplierBatchFee\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"networkName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"initPendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalPendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initNumBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalNewBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"overridePendingState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingStateTimeout\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"pendingStateTransitions\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"lastVerifiedBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"exitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"initPendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalPendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initNumBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalNewBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"proveNonDeterministicPendingState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupVerifier\",\"outputs\":[{\"internalType\":\"contractIVerifierRollup\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"globalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minForcedTimestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPolygonZkEVM.BatchData[]\",\"name\":\"batches\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"l2Coinbase\",\"type\":\"address\"}],\"name\":\"sequenceBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"globalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"minForcedTimestamp\",\"type\":\"uint64\"}],\"internalType\":\"structPolygonZkEVM.ForcedBatchData[]\",\"name\":\"batches\",\"type\":\"tuple[]\"}],\"name\":\"sequenceForceBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"sequencedBatches\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"accInputHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequencedTimestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"previousLastBatchSequenced\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newforceBatchTimeout\",\"type\":\"uint64\"}],\"name\":\"setForceBatchTimeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"newMultiplierBatchFee\",\"type\":\"uint16\"}],\"name\":\"setMultiplierBatchFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newPendingStateTimeout\",\"type\":\"uint64\"}],\"name\":\"setPendingStateTimeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTrustedAggregator\",\"type\":\"address\"}],\"name\":\"setTrustedAggregator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newTrustedAggregatorTimeout\",\"type\":\"uint64\"}],\"name\":\"setTrustedAggregatorTimeout\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTrustedSequencer\",\"type\":\"address\"}],\"name\":\"setTrustedSequencer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newTrustedSequencerURL\",\"type\":\"string\"}],\"name\":\"setTrustedSequencerURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"newVerifyBatchTimeTarget\",\"type\":\"uint64\"}],\"name\":\"setVerifyBatchTimeTarget\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"transferAdminRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedAggregator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedAggregatorTimeout\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedSequencer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedSequencerURL\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"verifyBatchTimeTarget\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"pendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initNumBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalNewBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"verifyBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"pendingStateNum\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"initNumBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"finalNewBatch\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"verifyBatchesTrustedAggregator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101406040523480156200001257600080fd5b5060405162004f5038038062004f508339810160408190526200003591620000a5565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b0391821661010052166101205262000131565b6001600160a01b03811681146200008557600080fd5b50565b80516001600160401b0381168114620000a057600080fd5b919050565b60008060008060008060c08789031215620000bf57600080fd5b8651620000cc816200006f565b6020880151909650620000df816200006f565b6040880151909550620000f2816200006f565b606088015190945062000105816200006f565b9250620001156080880162000088565b91506200012560a0880162000088565b90509295509295509295565b60805160a05160c05160e0516101005161012051614d51620001ff6000396000818161063801528181610d3201526126ef01526000818161077b0152610d0801526000818161072e0152818161192301528181612baf015261356f0152600081816108b9015281816111eb015281816115f3015281816120fa01528181612cd401528181612eb001526136e60152600081816109550152818161347601526139ac015260008181610830015281816118f101528181611d9301528181612e840152613a740152614d516000f3fe608060405234801561001057600080fd5b50600436106103ba5760003560e01c80638c3d7301116101f4578063c89e42df1161011a578063e7a7ed02116100ad578063f14916d61161007c578063f14916d61461099e578063f2fde38b146109b1578063f851a440146109c4578063f8b823e4146109d757600080fd5b8063e7a7ed0214610936578063e8bf92ed14610950578063eaeb077b14610977578063ed6b01041461098a57600080fd5b8063d8d1091b116100e9578063d8d1091b146108ee578063d939b31514610901578063dbc169761461091b578063e6ad707e1461092357600080fd5b8063c89e42df14610887578063cfa8ed471461089a578063d02103ca146108b4578063d2e129f9146108db57600080fd5b8063ada8f91911610192578063b6b0b09711610161578063b6b0b0971461082b578063ba58ae3914610852578063c0ed84e014610865578063c754c7ed1461086d57600080fd5b8063ada8f91914610763578063adc879e914610776578063afd23cbe1461079d578063b4d63f58146107cb57600080fd5b80639c9f3dfe116101ce5780639c9f3dfe14610703578063a066215c14610716578063a3c573eb14610729578063a50a164b1461075057600080fd5b80638c3d7301146106e25780638da5cb5b146106ea57806399f5634e146106fb57600080fd5b80634a910e6a116102e45780636b8616ce116102775780637fcb3653116102465780637fcb365314610620578063831c7ead14610633578063837a47381461065a578063841b24d7146106c857600080fd5b80636b8616ce146105d25780636ff512cc146105f2578063715018a6146106055780637215541a1461060d57600080fd5b8063542028d5116102b3578063542028d5146105a75780635e9145c9146105af5780635ec91958146105c257806360469169146105ca57600080fd5b80634a910e6a146105405780634e487706146105535780634fd70464146105665780635392c5e01461057957600080fd5b8063267822471161035c578063423fa8561161032b578063423fa856146104df57806345605267146104f9578063458c0477146105135780634a1a89a71461052657600080fd5b80632678224714610474578063298789831461049f578063383b3be8146104b9578063394218e9146104cc57600080fd5b806315064c961161039857806315064c961461041e5780631816b7e51461043b57806319d8ac611461044e578063220d78991461046157600080fd5b80630808270c146103bf5780630a0d9fbe146103d4578063107bf28c14610409575b600080fd5b6103d26103cd366004614303565b6109e0565b005b606f546103ec9061010090046001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b610411610a79565b60405161040091906143eb565b606f5461042b9060ff1681565b6040519015158152602001610400565b6103d26104493660046143fe565b610b07565b6073546103ec906001600160401b031681565b61041161046f366004614422565b610be5565b607b54610487906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b60745461048790600160401b90046001600160a01b031681565b61042b6104c736600461446f565b610d90565b6103d26104da36600461446f565b610dd7565b6073546103ec90600160401b90046001600160401b031681565b6073546103ec90600160801b90046001600160401b031681565b6079546103ec906001600160401b031681565b6079546103ec90600160401b90046001600160401b031681565b6103d261054e36600461446f565b610eef565b6103d261056136600461446f565b610f77565b6103d261057436600461448a565b61107e565b61059961058736600461446f565b60756020526000908152604090205481565b604051908152602001610400565b610411611358565b6103d26105bd36600461456d565b611365565b6103d26119d4565b610599611a95565b6105996105e036600461446f565b60716020526000908152604090205481565b6103d26106003660046145c0565b611aab565b6103d2611b45565b6103d261061b36600461446f565b611b59565b6074546103ec906001600160401b031681565b6103ec7f000000000000000000000000000000000000000000000000000000000000000081565b61069d6106683660046145db565b6078602052600090815260409020805460018201546002909201546001600160401b0380831693600160401b90930416919084565b604080516001600160401b039586168152949093166020850152918301526060820152608001610400565b6079546103ec90600160c01b90046001600160401b031681565b6103d2611cb1565b6033546001600160a01b0316610487565b610599611d58565b6103d261071136600461446f565b611e7b565b6103d261072436600461446f565b611f87565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d261075e36600461448a565b61204f565b6103d26107713660046145c0565b61219b565b6103ec7f000000000000000000000000000000000000000000000000000000000000000081565b606f546107b8906901000000000000000000900461ffff1681565b60405161ffff9091168152602001610400565b6108066107d936600461446f565b607260205260009081526040902080546001909101546001600160401b0380821691600160401b90041683565b604080519384526001600160401b039283166020850152911690820152606001610400565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b61042b6108603660046145db565b612221565b6103ec6122a8565b607b546103ec90600160a01b90046001600160401b031681565b6103d2610895366004614696565b6122f5565b606f5461048790600160581b90046001600160a01b031681565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d26108e93660046146d2565b61235c565b6103d26108fc366004614784565b612777565b6079546103ec90600160801b90046001600160401b031681565b6103d2612b82565b6103d2610931366004614303565b612c28565b6073546103ec90600160c01b90046001600160401b031681565b6104877f000000000000000000000000000000000000000000000000000000000000000081565b6103d26109853660046147c5565b612dbf565b607b5461042b90600160e01b900460ff1681565b6103d26109ac3660046145c0565b6130bb565b6103d26109bf3660046145c0565b613155565b607a54610487906001600160a01b031681565b61059960705481565b606f5460ff1615610a0457604051630bc011ff60e21b815260040160405180910390fd5b610a1488888888888888886131e2565b6001600160401b0385166000908152607560209081526040918290205482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a1610a6f61356d565b5050505050505050565b60778054610a8690614810565b80601f0160208091040260200160405190810160405280929190818152602001828054610ab290614810565b8015610aff5780601f10610ad457610100808354040283529160200191610aff565b820191906000526020600020905b815481529060010190602001808311610ae257829003601f168201915b505050505081565b607a546001600160a01b03163314610b3257604051634755657960e01b815260040160405180910390fd5b6103e88161ffff161080610b4b57506103ff8161ffff16115b15610b82576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80546affff0000000000000000001916690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b6001600160401b038086166000818152607260205260408082205493881682529020546060929115801590610c18575081155b15610c4f576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610c86576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8f84612221565b610cc5576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516bffffffffffffffffffffffff193360601b166020820152603481019690965260548601929092526001600160c01b031960c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b6079546001600160401b0382811660009081526078602052604081205490924292610dc692600160801b90920481169116614860565b6001600160401b0316111592915050565b607a546001600160a01b03163314610e0257604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115610e2f57604051631d06e87960e01b815260040160405180910390fd5b606f5460ff16610e88576079546001600160401b03600160c01b909104811690821610610e88576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b6001600160401b038416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610bda565b607454600160401b90046001600160a01b03163314610f6b57606f5460ff1615610f2c57604051630bc011ff60e21b815260040160405180910390fd5b610f3581610d90565b610f6b576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f74816135e8565b50565b607a546001600160a01b03163314610fa257604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115610fcf5760405163f5e37f2f60e01b815260040160405180910390fd5b606f5460ff1661100f57607b546001600160401b03600160a01b90910481169082161061100f5760405163f5e37f2f60e01b815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b6001600160401b038416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610bda565b606f5460ff16156110a257604051630bc011ff60e21b815260040160405180910390fd5b6079546001600160401b0386811660009081526072602052604090206001015442926110d992600160c01b90910481169116614860565b6001600160401b0316111561111a576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e86111278787614887565b6001600160401b0316111561114f57604051635acfba9d60e11b815260040160405180910390fd5b61115e878787878787876137a0565b61116785613a9b565b607954600160801b90046001600160401b0316600003611254576074805467ffffffffffffffff19166001600160401b03878116918217909255600090815260756020526040902084905560795416156111d557607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561123757600080fd5b505af115801561124b573d6000803e3d6000fd5b5050505061130e565b61125c613c70565b607980546001600160401b0316906000611275836148a7565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815288831660208083019182528284018a8152606084018a8152607954871660009081526078909352949091209251835492518616600160401b026fffffffffffffffffffffffffffffffff199093169516949094171781559151600183015551600290910155505b60405183815233906001600160401b038716907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966906020015b60405180910390a350505050505050565b60768054610a8690614810565b606f5460ff161561138957604051630bc011ff60e21b815260040160405180910390fd5b606f54600160581b90046001600160a01b031633146113d4576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160008190036113f75760405163cb591a5f60e01b815260040160405180910390fd5b6103e881111561141a57604051635acfba9d60e11b815260040160405180910390fd5b6073546001600160401b03600160401b82048116600081815260726020526040812054838516949293600160801b909304909216919082905b868110156117b15760008a8a8381811061146f5761146f6148cd565b905060200281019061148191906148e3565b61148a90614903565b805180516020909101206060820151919250906001600160401b0316156115b057856114b5816148a7565b965050600081836020015184606001516040516020016114f593929190928352602083019190915260c01b6001600160c01b031916604082015260480190565b60408051601f1981840301815291815281516020928301206001600160401b038a166000908152607190935291205490915081146115465760405163671ebaaf60e11b815260040160405180910390fd5b6001600160401b0380881660009081526071602052604080822091909155606085015190850151908216911610156115aa576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506116c7565b60208201511580159061166a575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063257b3632906024016020604051808303816000875af1158015611644573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611668919061498f565b155b156116a1576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156116c7576040516328a69b1f60e21b815260040160405180910390fd5b876001600160401b031682604001516001600160401b031610806116f757504282604001516001600160401b0316115b1561172e576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b6001600160c01b03191660808301528b901b6bffffffffffffffffffffffff19166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806117a9906149a8565b915050611453565b506117bc8685614860565b6073549094506001600160401b03600160c01b909104811690841611156117f65760405163c630a00d60e01b815260040160405180910390fd5b60006118028285614887565b611815906001600160401b0316886149c1565b60408051606081018252858152426001600160401b03908116602080840191825260738054600160401b9081900485168688019081528d861660008181526072909552979093209551865592516001909501805492519585166fffffffffffffffffffffffffffffffff199384161795851684029590951790945583548c84169116179302929092179055909150828116908516146118d4576073805467ffffffffffffffff60801b1916600160801b6001600160401b038716021790555b6119193330836070546118e791906149da565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016929190613d14565b611921613c70565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166379e2cf976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b50506040516001600160401b03881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce9150600090a250505050505050505050565b607a546001600160a01b031633146119ff57604051634755657960e01b815260040160405180910390fd5b607b54600160e01b900460ff16611a42576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f90600090a1565b60006070546064611aa691906149da565b905090565b607a546001600160a01b03163314611ad657604051634755657960e01b815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff16600160581b6001600160a01b038416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610bda565b611b4d613dcb565b611b576000613e25565b565b6033546001600160a01b03163314611ca9576000611b756122a8565b9050806001600160401b0316826001600160401b031611611bc2576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6073546001600160401b03600160401b90910481169083161180611c0157506001600160401b0380831660009081526072602052604090206001015416155b15611c38576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b038083166000908152607260205260409020600101544291611c669162093a809116614860565b6001600160401b03161115611ca7576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b610f7461356d565b607b546001600160a01b03163314611cf5576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dfe919061498f565b90506000611e0a6122a8565b6073546001600160401b03600160401b8204811691611e3a91600160801b8204811691600160c01b900416614887565b611e449190614860565b611e4e9190614887565b6001600160401b0316905080600003611e6a5760009250505090565b611e748183614a07565b9250505090565b607a546001600160a01b03163314611ea657604051634755657960e01b815260040160405180910390fd5b62093a806001600160401b0382161115611ed357604051630cc9650760e41b815260040160405180910390fd5b606f5460ff16611f2c576079546001600160401b03600160801b909104811690821610611f2c576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805467ffffffffffffffff60801b1916600160801b6001600160401b038416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610bda565b607a546001600160a01b03163314611fb257604051634755657960e01b815260040160405180910390fd5b62015180816001600160401b03161115611ff8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f805468ffffffffffffffff0019166101006001600160401b038416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610bda565b607454600160401b90046001600160a01b031633146120815760405163bbcbbc0560e01b815260040160405180910390fd5b612090878787878787876137a0565b6074805467ffffffffffffffff19166001600160401b03878116918217909255600090815260756020526040902084905560795416156120e457607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561214657600080fd5b505af115801561215a573d6000803e3d6000fd5b50506040518581523392506001600160401b03881691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe90602001611347565b607a546001600160a01b031633146121c657604051634755657960e01b815260040160405180910390fd5b607b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610bda565b600067ffffffff000000016001600160401b038316108015612257575067ffffffff00000001604083901c6001600160401b0316105b8015612277575067ffffffff00000001608083901c6001600160401b0316105b801561228e575067ffffffff0000000160c083901c105b1561229b57506001919050565b506000919050565b919050565b6079546000906001600160401b0316156122e557506079546001600160401b03908116600090815260786020526040902054600160401b90041690565b506074546001600160401b031690565b607a546001600160a01b0316331461232057604051634755657960e01b815260040160405180910390fd5b607661232c8282614a69565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610bda91906143eb565b600054610100900460ff161580801561237c5750600054600160ff909116105b806123965750303b158015612396575060005460ff166001145b61240d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015612430576000805461ff0019166101001790555b61243d60208801886145c0565b607a805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905561247a60408801602089016145c0565b606f80546001600160a01b0392909216600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff9092169190911790556124ca60808801606089016145c0565b607480546001600160a01b0392909216600160401b027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790556000805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad86905560766125438682614a69565b5060776125508582614a69565b5062093a806125656060890160408a0161446f565b6001600160401b0316111561258d57604051630cc9650760e41b815260040160405180910390fd5b61259d606088016040890161446f565b607980546001600160401b0392909216600160801b0267ffffffffffffffff60801b1990921691909117905562093a806125dd60a0890160808a0161446f565b6001600160401b0316111561260557604051631d06e87960e01b815260040160405180910390fd5b61261560a088016080890161446f565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b6001600160401b03939093169290920291909117905567016345785d8a0000607055606f80546affffffffffffffffffff0019166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556126ca613e84565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd660007f000000000000000000000000000000000000000000000000000000000000000085856040516127209493929190614b51565b60405180910390a1801561276e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b607b54600160e01b900460ff16156127a2576040516324eff8c360e01b815260040160405180910390fd5b606f5460ff16156127c657604051630bc011ff60e21b815260040160405180910390fd5b8060008190036127e95760405163cb591a5f60e01b815260040160405180910390fd5b6103e881111561280c57604051635acfba9d60e11b815260040160405180910390fd5b6073546001600160401b03600160c01b8204811691612834918491600160801b900416614b88565b11156128535760405163c630a00d60e01b815260040160405180910390fd5b6073546001600160401b03600160401b820481166000818152607260205260408120549193600160801b9004909216915b84811015612a6c5760008787838181106128a0576128a06148cd565b90506020028101906128b29190614b9b565b6128bb90614bb1565b9050836128c7816148a7565b825180516020918201208185015160408087015190519499509194506000936129119386939101928352602083019190915260c01b6001600160c01b031916604082015260480190565b60408051601f1981840301815291815281516020928301206001600160401b0389166000908152607190935291205490915081146129625760405163671ebaaf60e11b815260040160405180910390fd5b6001600160401b0386166000908152607160205260408120556129866001896149c1565b84036129f35742607b60149054906101000a90046001600160401b031684604001516129b29190614860565b6001600160401b031611156129f3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b6001600160c01b031916608083015233901b6bffffffffffffffffffffffff19166088820152609c016040516020818303038152906040528051906020012094505050508080612a64906149a8565b915050612884565b50612a778484614860565b607380546001600160401b0342811667ffffffffffffffff199092168217808455604080516060810182528781526020808201958652600160401b9384900485168284019081528589166000818152607290935284832093518455965160019390930180549151871686026fffffffffffffffffffffffffffffffff1990921693871693909317179091558554938916600160801b0267ffffffffffffffff60801b19938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a546001600160a01b03163314612bad57604051634755657960e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dbc169766040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612c0857600080fd5b505af1158015612c1c573d6000803e3d6000fd5b50505050611b57613f0a565b607454600160401b90046001600160a01b03163314612c5a5760405163bbcbbc0560e01b815260040160405180910390fd5b612c6a88888888888888886131e2565b6074805467ffffffffffffffff19166001600160401b0387811691821790925560009081526075602052604090208490556079541615612cbe57607980546fffffffffffffffffffffffffffffffff191690555b6040516333d6247d60e01b8152600481018590527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b158015612d2057600080fd5b505af1158015612d34573d6000803e3d6000fd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a80000000000000000000000000000000000000000000000000179055505060405183815233906001600160401b038716907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a35050505050505050565b607b54600160e01b900460ff1615612dea576040516324eff8c360e01b815260040160405180910390fd5b606f5460ff1615612e0e57604051630bc011ff60e21b815260040160405180910390fd5b6000612e18611a95565b905081811115612e54576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115612e77576040516328a69b1f60e21b815260040160405180910390fd5b612eac6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084613d14565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f30919061498f565b60738054919250600160c01b9091046001600160401b0316906018612f54836148a7565b91906101000a8154816001600160401b0302191690836001600160401b03160217905550508484604051612f89929190614c2c565b60408051918290038220602083015281018290526001600160c01b03194260c01b16606082015260680160408051808303601f190181529181528151602092830120607354600160c01b90046001600160401b03166000908152607190935291205532330361305757607354604080518381523360208201526060918101829052600091810191909152600160c01b9091046001600160401b0316907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26130b4565b607360189054906101000a90046001600160401b03166001600160401b03167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516130ab9493929190614c3c565b60405180910390a25b5050505050565b607a546001600160a01b031633146130e657604051634755657960e01b815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610bda565b61315d613dcb565b6001600160a01b0381166131d95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612404565b610f7481613e25565b60006001600160401b03891615613276576079546001600160401b03908116908a1611156132235760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038089166000908152607860205260409020600281015481549092898116600160401b909204161461327057604051632bd2e3e760e01b815260040160405180910390fd5b506132de565b506001600160401b038616600090815260756020526040902054806132ae576040516324cbdcc360e11b815260040160405180910390fd5b6074546001600160401b0390811690881611156132de57604051630f2b74f160e11b815260040160405180910390fd5b6079546001600160401b03908116908916118061330d5750886001600160401b0316886001600160401b031611155b8061332e57506079546001600160401b03600160401b909104811690891611155b15613365576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b03888116600090815260786020526040902054600160401b90048116908716146133c2576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006133d18888888589610be5565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516134069190614c65565b602060405180830381855afa158015613423573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190613446919061498f565b6134509190614c77565b604080516020810182528281529051632363e29760e21b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916134ad9189918991600401614c8b565b602060405180830381865afa1580156134ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ee9190614cd3565b61350b576040516309bde33960e01b815260040160405180910390fd5b6001600160401b038a16600090815260786020526040902060020154869003613560576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156135c857600080fd5b505af11580156135dc573d6000803e3d6000fd5b50505050611b57613f7b565b6079546001600160401b03600160401b909104811690821611158061361b57506079546001600160401b03908116908216115b15613652576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160401b038181166000818152607860209081526040808320805460748054600160401b9283900490981667ffffffffffffffff1990981688179055600282015487865260759094529382902092909255607980546fffffffffffffffff000000000000000019169390940292909217909255600182015490516333d6247d60e01b815260048101919091529091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906333d6247d90602401600060405180830381600087803b15801561373257600080fd5b505af1158015613746573d6000803e3d6000fd5b50505050826001600160401b0316816001600160401b03167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161379391815260200190565b60405180910390a3505050565b6000806137ab6122a8565b90506001600160401b03891615613841576079546001600160401b03908116908a1611156137ec5760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a1660009081526078602052604090206002810154815490945090918a8116600160401b909204161461383b57604051632bd2e3e760e01b815260040160405180910390fd5b506138ad565b6001600160401b03881660009081526075602052604090205491508161387a576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156138ad57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b0316116138f8576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613907898989868a610be5565b905060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161393c9190614c65565b602060405180830381855afa158015613959573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061397c919061498f565b6139869190614c77565b604080516020810182528281529051632363e29760e21b81529192506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638d8f8a5c916139e3918a918a91600401614c8b565b602060405180830381865afa158015613a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a249190614cd3565b613a41576040516309bde33960e01b815260040160405180910390fd5b61356033613a4f858c614887565b6001600160401b0316613a60611d58565b613a6a91906149da565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190613fd7565b6000613aa56122a8565b905081600080613ab58484614887565b606f546001600160401b039182169250600091613ad891610100900416426149c1565b90505b846001600160401b0316846001600160401b031614613b59576001600160401b0380851660009081526072602052604090206001810154909116821015613b38576001810154600160401b90046001600160401b03169450613b53565b613b428686614887565b6001600160401b0316935050613b59565b50613adb565b6000613b6584846149c1565b905083811015613bbc57808403600c8111613b805780613b83565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281613bb257613bb26149f1565b0460705550613c2c565b838103600c8111613bcd5780613bd0565b600c5b90506000816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281613c0757613c076149f1565b04905080607054670de0b6b3a76400000281613c2557613c256149f1565b0460705550505b683635c9adc5dea000006070541115613c5157683635c9adc5dea0000060705561276e565b633b9aca00607054101561276e57633b9aca0060705550505050505050565b6079546001600160401b03600160401b8204811691161115611b5757607954600090613cad90600160401b90046001600160401b03166001614860565b9050613cb881610d90565b15610f7457607954600090600290613cda9084906001600160401b0316614887565b613ce49190614cf5565b613cee9083614860565b9050613cf981610d90565b15613d0b57613d07816135e8565b5050565b613d07826135e8565b6040516001600160a01b0380851660248301528316604482015260648101829052613dc59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614025565b50505050565b6033546001600160a01b03163314611b575760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612404565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16613f015760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612404565b611b5733613e25565b606f5460ff16613f46576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b606f5460ff1615613f9f57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b6040516001600160a01b0383166024820152604481018290526140209084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401613d61565b505050565b600061407a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661410a9092919063ffffffff16565b80519091501561402057808060200190518101906140989190614cd3565b6140205760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612404565b60606141198484600085614123565b90505b9392505050565b60608247101561419b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612404565b6001600160a01b0385163b6141f25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612404565b600080866001600160a01b0316858760405161420e9190614c65565b60006040518083038185875af1925050503d806000811461424b576040519150601f19603f3d011682016040523d82523d6000602084013e614250565b606091505b509150915061426082828661426b565b979650505050505050565b6060831561427a57508161411c565b82511561428a5782518084602001fd5b8160405162461bcd60e51b815260040161240491906143eb565b80356001600160401b03811681146122a357600080fd5b60008083601f8401126142cd57600080fd5b5081356001600160401b038111156142e457600080fd5b6020830191508360208285010111156142fc57600080fd5b9250929050565b60008060008060008060008060e0898b03121561431f57600080fd5b614328896142a4565b975061433660208a016142a4565b965061434460408a016142a4565b955061435260608a016142a4565b94506080890135935060a0890135925060c08901356001600160401b0381111561437b57600080fd5b6143878b828c016142bb565b999c989b5096995094979396929594505050565b60005b838110156143b657818101518382015260200161439e565b50506000910152565b600081518084526143d781602086016020860161439b565b601f01601f19169290920160200192915050565b60208152600061411c60208301846143bf565b60006020828403121561441057600080fd5b813561ffff8116811461411c57600080fd5b600080600080600060a0868803121561443a57600080fd5b614443866142a4565b9450614451602087016142a4565b94979496505050506040830135926060810135926080909101359150565b60006020828403121561448157600080fd5b61411c826142a4565b600080600080600080600060c0888a0312156144a557600080fd5b6144ae886142a4565b96506144bc602089016142a4565b95506144ca604089016142a4565b9450606088013593506080880135925060a08801356001600160401b038111156144f357600080fd5b6144ff8a828b016142bb565b989b979a50959850939692959293505050565b60008083601f84011261452457600080fd5b5081356001600160401b0381111561453b57600080fd5b6020830191508360208260051b85010111156142fc57600080fd5b80356001600160a01b03811681146122a357600080fd5b60008060006040848603121561458257600080fd5b83356001600160401b0381111561459857600080fd5b6145a486828701614512565b90945092506145b7905060208501614556565b90509250925092565b6000602082840312156145d257600080fd5b61411c82614556565b6000602082840312156145ed57600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261461b57600080fd5b81356001600160401b0380821115614635576146356145f4565b604051601f8301601f19908116603f0116810190828211818310171561465d5761465d6145f4565b8160405283815286602085880101111561467657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156146a857600080fd5b81356001600160401b038111156146be57600080fd5b6146ca8482850161460a565b949350505050565b6000806000806000808688036101208112156146ed57600080fd5b60a08112156146fb57600080fd5b5086955060a0870135945060c08701356001600160401b038082111561472057600080fd5b61472c8a838b0161460a565b955060e089013591508082111561474257600080fd5b61474e8a838b0161460a565b945061010089013591508082111561476557600080fd5b5061477289828a016142bb565b979a9699509497509295939492505050565b6000806020838503121561479757600080fd5b82356001600160401b038111156147ad57600080fd5b6147b985828601614512565b90969095509350505050565b6000806000604084860312156147da57600080fd5b83356001600160401b038111156147f057600080fd5b6147fc868287016142bb565b909790965060209590950135949350505050565b600181811c9082168061482457607f821691505b60208210810361484457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156148805761488061484a565b5092915050565b6001600160401b038281168282160390808211156148805761488061484a565b60006001600160401b038083168181036148c3576148c361484a565b6001019392505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e198336030181126148f957600080fd5b9190910192915050565b60006080823603121561491557600080fd5b604051608081016001600160401b038282108183111715614938576149386145f4565b81604052843591508082111561494d57600080fd5b5061495a3682860161460a565b82525060208301356020820152614973604084016142a4565b6040820152614984606084016142a4565b606082015292915050565b6000602082840312156149a157600080fd5b5051919050565b6000600182016149ba576149ba61484a565b5060010190565b818103818111156149d4576149d461484a565b92915050565b80820281158282048414176149d4576149d461484a565b634e487b7160e01b600052601260045260246000fd5b600082614a1657614a166149f1565b500490565b601f82111561402057600081815260208120601f850160051c81016020861015614a425750805b601f850160051c820191505b81811015614a6157828155600101614a4e565b505050505050565b81516001600160401b03811115614a8257614a826145f4565b614a9681614a908454614810565b84614a1b565b602080601f831160018114614acb5760008415614ab35750858301515b600019600386901b1c1916600185901b178555614a61565b600085815260208120601f198616915b82811015614afa57888601518255948401946001909101908401614adb565b5085821015614b185787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160401b03808716835280861660208401525060606040830152614b7e606083018486614b28565b9695505050505050565b808201808211156149d4576149d461484a565b60008235605e198336030181126148f957600080fd5b600060608236031215614bc357600080fd5b604051606081016001600160401b038282108183111715614be657614be66145f4565b816040528435915080821115614bfb57600080fd5b50614c083682860161460a565b82525060208301356020820152614c21604084016142a4565b604082015292915050565b8183823760009101908152919050565b8481526001600160a01b0384166020820152606060408201526000614b7e606083018486614b28565b600082516148f981846020870161439b565b600082614c8657614c866149f1565b500690565b604081526000614c9f604083018587614b28565b905060208083018460005b6001811015614cc757815183529183019190830190600101614caa565b50505050949350505050565b600060208284031215614ce557600080fd5b8151801515811461411c57600080fd5b60006001600160401b0380841680614d0f57614d0f6149f1565b9216919091049291505056fea26469706673582212200b586a4d2a78f3585b9b741ea1f06c0afab4d66b48c408bc1e7be9fa34df798364736f6c63430008110033", +} + +// PolygonzkevmABI is the input ABI used to generate the binding from. +// Deprecated: Use PolygonzkevmMetaData.ABI instead. +var PolygonzkevmABI = PolygonzkevmMetaData.ABI + +// PolygonzkevmBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use PolygonzkevmMetaData.Bin instead. +var PolygonzkevmBin = PolygonzkevmMetaData.Bin + +// DeployPolygonzkevm deploys a new Ethereum contract, binding an instance of Polygonzkevm to it. +func DeployPolygonzkevm(auth *bind.TransactOpts, backend bind.ContractBackend, _globalExitRootManager common.Address, _matic common.Address, _rollupVerifier common.Address, _bridgeAddress common.Address, _chainID uint64, _forkID uint64) (common.Address, *types.Transaction, *Polygonzkevm, error) { + parsed, err := PolygonzkevmMetaData.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(PolygonzkevmBin), backend, _globalExitRootManager, _matic, _rollupVerifier, _bridgeAddress, _chainID, _forkID) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Polygonzkevm{PolygonzkevmCaller: PolygonzkevmCaller{contract: contract}, PolygonzkevmTransactor: PolygonzkevmTransactor{contract: contract}, PolygonzkevmFilterer: PolygonzkevmFilterer{contract: contract}}, nil +} + +// Polygonzkevm is an auto generated Go binding around an Ethereum contract. +type Polygonzkevm struct { + PolygonzkevmCaller // Read-only binding to the contract + PolygonzkevmTransactor // Write-only binding to the contract + PolygonzkevmFilterer // Log filterer for contract events +} + +// PolygonzkevmCaller is an auto generated read-only Go binding around an Ethereum contract. +type PolygonzkevmCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PolygonzkevmTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PolygonzkevmFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PolygonzkevmSession struct { + Contract *Polygonzkevm // 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 +} + +// PolygonzkevmCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PolygonzkevmCallerSession struct { + Contract *PolygonzkevmCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PolygonzkevmTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PolygonzkevmTransactorSession struct { + Contract *PolygonzkevmTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PolygonzkevmRaw is an auto generated low-level Go binding around an Ethereum contract. +type PolygonzkevmRaw struct { + Contract *Polygonzkevm // Generic contract binding to access the raw methods on +} + +// PolygonzkevmCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PolygonzkevmCallerRaw struct { + Contract *PolygonzkevmCaller // Generic read-only contract binding to access the raw methods on +} + +// PolygonzkevmTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PolygonzkevmTransactorRaw struct { + Contract *PolygonzkevmTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPolygonzkevm creates a new instance of Polygonzkevm, bound to a specific deployed contract. +func NewPolygonzkevm(address common.Address, backend bind.ContractBackend) (*Polygonzkevm, error) { + contract, err := bindPolygonzkevm(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Polygonzkevm{PolygonzkevmCaller: PolygonzkevmCaller{contract: contract}, PolygonzkevmTransactor: PolygonzkevmTransactor{contract: contract}, PolygonzkevmFilterer: PolygonzkevmFilterer{contract: contract}}, nil +} + +// NewPolygonzkevmCaller creates a new read-only instance of Polygonzkevm, bound to a specific deployed contract. +func NewPolygonzkevmCaller(address common.Address, caller bind.ContractCaller) (*PolygonzkevmCaller, error) { + contract, err := bindPolygonzkevm(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmCaller{contract: contract}, nil +} + +// NewPolygonzkevmTransactor creates a new write-only instance of Polygonzkevm, bound to a specific deployed contract. +func NewPolygonzkevmTransactor(address common.Address, transactor bind.ContractTransactor) (*PolygonzkevmTransactor, error) { + contract, err := bindPolygonzkevm(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmTransactor{contract: contract}, nil +} + +// NewPolygonzkevmFilterer creates a new log filterer instance of Polygonzkevm, bound to a specific deployed contract. +func NewPolygonzkevmFilterer(address common.Address, filterer bind.ContractFilterer) (*PolygonzkevmFilterer, error) { + contract, err := bindPolygonzkevm(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PolygonzkevmFilterer{contract: contract}, nil +} + +// bindPolygonzkevm binds a generic wrapper to an already deployed contract. +func bindPolygonzkevm(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PolygonzkevmMetaData.GetAbi() + 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 (_Polygonzkevm *PolygonzkevmRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevm.Contract.PolygonzkevmCaller.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 (_Polygonzkevm *PolygonzkevmRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.Contract.PolygonzkevmTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevm *PolygonzkevmRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevm.Contract.PolygonzkevmTransactor.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 (_Polygonzkevm *PolygonzkevmCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevm.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 (_Polygonzkevm *PolygonzkevmTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevm *PolygonzkevmTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevm.Contract.contract.Transact(opts, method, params...) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) Admin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "admin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) Admin() (common.Address, error) { + return _Polygonzkevm.Contract.Admin(&_Polygonzkevm.CallOpts) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) Admin() (common.Address, error) { + return _Polygonzkevm.Contract.Admin(&_Polygonzkevm.CallOpts) +} + +// BatchFee is a free data retrieval call binding the contract method 0xf8b823e4. +// +// Solidity: function batchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCaller) BatchFee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "batchFee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BatchFee is a free data retrieval call binding the contract method 0xf8b823e4. +// +// Solidity: function batchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmSession) BatchFee() (*big.Int, error) { + return _Polygonzkevm.Contract.BatchFee(&_Polygonzkevm.CallOpts) +} + +// BatchFee is a free data retrieval call binding the contract method 0xf8b823e4. +// +// Solidity: function batchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCallerSession) BatchFee() (*big.Int, error) { + return _Polygonzkevm.Contract.BatchFee(&_Polygonzkevm.CallOpts) +} + +// BatchNumToStateRoot is a free data retrieval call binding the contract method 0x5392c5e0. +// +// Solidity: function batchNumToStateRoot(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmCaller) BatchNumToStateRoot(opts *bind.CallOpts, arg0 uint64) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "batchNumToStateRoot", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// BatchNumToStateRoot is a free data retrieval call binding the contract method 0x5392c5e0. +// +// Solidity: function batchNumToStateRoot(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmSession) BatchNumToStateRoot(arg0 uint64) ([32]byte, error) { + return _Polygonzkevm.Contract.BatchNumToStateRoot(&_Polygonzkevm.CallOpts, arg0) +} + +// BatchNumToStateRoot is a free data retrieval call binding the contract method 0x5392c5e0. +// +// Solidity: function batchNumToStateRoot(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmCallerSession) BatchNumToStateRoot(arg0 uint64) ([32]byte, error) { + return _Polygonzkevm.Contract.BatchNumToStateRoot(&_Polygonzkevm.CallOpts, arg0) +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) BridgeAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "bridgeAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) BridgeAddress() (common.Address, error) { + return _Polygonzkevm.Contract.BridgeAddress(&_Polygonzkevm.CallOpts) +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) BridgeAddress() (common.Address, error) { + return _Polygonzkevm.Contract.BridgeAddress(&_Polygonzkevm.CallOpts) +} + +// CalculateRewardPerBatch is a free data retrieval call binding the contract method 0x99f5634e. +// +// Solidity: function calculateRewardPerBatch() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCaller) CalculateRewardPerBatch(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "calculateRewardPerBatch") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CalculateRewardPerBatch is a free data retrieval call binding the contract method 0x99f5634e. +// +// Solidity: function calculateRewardPerBatch() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmSession) CalculateRewardPerBatch() (*big.Int, error) { + return _Polygonzkevm.Contract.CalculateRewardPerBatch(&_Polygonzkevm.CallOpts) +} + +// CalculateRewardPerBatch is a free data retrieval call binding the contract method 0x99f5634e. +// +// Solidity: function calculateRewardPerBatch() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCallerSession) CalculateRewardPerBatch() (*big.Int, error) { + return _Polygonzkevm.Contract.CalculateRewardPerBatch(&_Polygonzkevm.CallOpts) +} + +// ChainID is a free data retrieval call binding the contract method 0xadc879e9. +// +// Solidity: function chainID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) ChainID(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "chainID") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// ChainID is a free data retrieval call binding the contract method 0xadc879e9. +// +// Solidity: function chainID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) ChainID() (uint64, error) { + return _Polygonzkevm.Contract.ChainID(&_Polygonzkevm.CallOpts) +} + +// ChainID is a free data retrieval call binding the contract method 0xadc879e9. +// +// Solidity: function chainID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) ChainID() (uint64, error) { + return _Polygonzkevm.Contract.ChainID(&_Polygonzkevm.CallOpts) +} + +// CheckStateRootInsidePrime is a free data retrieval call binding the contract method 0xba58ae39. +// +// Solidity: function checkStateRootInsidePrime(uint256 newStateRoot) pure returns(bool) +func (_Polygonzkevm *PolygonzkevmCaller) CheckStateRootInsidePrime(opts *bind.CallOpts, newStateRoot *big.Int) (bool, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "checkStateRootInsidePrime", newStateRoot) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// CheckStateRootInsidePrime is a free data retrieval call binding the contract method 0xba58ae39. +// +// Solidity: function checkStateRootInsidePrime(uint256 newStateRoot) pure returns(bool) +func (_Polygonzkevm *PolygonzkevmSession) CheckStateRootInsidePrime(newStateRoot *big.Int) (bool, error) { + return _Polygonzkevm.Contract.CheckStateRootInsidePrime(&_Polygonzkevm.CallOpts, newStateRoot) +} + +// CheckStateRootInsidePrime is a free data retrieval call binding the contract method 0xba58ae39. +// +// Solidity: function checkStateRootInsidePrime(uint256 newStateRoot) pure returns(bool) +func (_Polygonzkevm *PolygonzkevmCallerSession) CheckStateRootInsidePrime(newStateRoot *big.Int) (bool, error) { + return _Polygonzkevm.Contract.CheckStateRootInsidePrime(&_Polygonzkevm.CallOpts, newStateRoot) +} + +// ForceBatchTimeout is a free data retrieval call binding the contract method 0xc754c7ed. +// +// Solidity: function forceBatchTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) ForceBatchTimeout(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "forceBatchTimeout") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// ForceBatchTimeout is a free data retrieval call binding the contract method 0xc754c7ed. +// +// Solidity: function forceBatchTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) ForceBatchTimeout() (uint64, error) { + return _Polygonzkevm.Contract.ForceBatchTimeout(&_Polygonzkevm.CallOpts) +} + +// ForceBatchTimeout is a free data retrieval call binding the contract method 0xc754c7ed. +// +// Solidity: function forceBatchTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) ForceBatchTimeout() (uint64, error) { + return _Polygonzkevm.Contract.ForceBatchTimeout(&_Polygonzkevm.CallOpts) +} + +// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. +// +// Solidity: function forcedBatches(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmCaller) ForcedBatches(opts *bind.CallOpts, arg0 uint64) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "forcedBatches", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. +// +// Solidity: function forcedBatches(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmSession) ForcedBatches(arg0 uint64) ([32]byte, error) { + return _Polygonzkevm.Contract.ForcedBatches(&_Polygonzkevm.CallOpts, arg0) +} + +// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. +// +// Solidity: function forcedBatches(uint64 ) view returns(bytes32) +func (_Polygonzkevm *PolygonzkevmCallerSession) ForcedBatches(arg0 uint64) ([32]byte, error) { + return _Polygonzkevm.Contract.ForcedBatches(&_Polygonzkevm.CallOpts, arg0) +} + +// ForkID is a free data retrieval call binding the contract method 0x831c7ead. +// +// Solidity: function forkID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) ForkID(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "forkID") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// ForkID is a free data retrieval call binding the contract method 0x831c7ead. +// +// Solidity: function forkID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) ForkID() (uint64, error) { + return _Polygonzkevm.Contract.ForkID(&_Polygonzkevm.CallOpts) +} + +// ForkID is a free data retrieval call binding the contract method 0x831c7ead. +// +// Solidity: function forkID() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) ForkID() (uint64, error) { + return _Polygonzkevm.Contract.ForkID(&_Polygonzkevm.CallOpts) +} + +// GetForcedBatchFee is a free data retrieval call binding the contract method 0x60469169. +// +// Solidity: function getForcedBatchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCaller) GetForcedBatchFee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "getForcedBatchFee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetForcedBatchFee is a free data retrieval call binding the contract method 0x60469169. +// +// Solidity: function getForcedBatchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmSession) GetForcedBatchFee() (*big.Int, error) { + return _Polygonzkevm.Contract.GetForcedBatchFee(&_Polygonzkevm.CallOpts) +} + +// GetForcedBatchFee is a free data retrieval call binding the contract method 0x60469169. +// +// Solidity: function getForcedBatchFee() view returns(uint256) +func (_Polygonzkevm *PolygonzkevmCallerSession) GetForcedBatchFee() (*big.Int, error) { + return _Polygonzkevm.Contract.GetForcedBatchFee(&_Polygonzkevm.CallOpts) +} + +// GetInputSnarkBytes is a free data retrieval call binding the contract method 0x220d7899. +// +// Solidity: function getInputSnarkBytes(uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 oldStateRoot, bytes32 newStateRoot) view returns(bytes) +func (_Polygonzkevm *PolygonzkevmCaller) GetInputSnarkBytes(opts *bind.CallOpts, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, oldStateRoot [32]byte, newStateRoot [32]byte) ([]byte, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "getInputSnarkBytes", initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// GetInputSnarkBytes is a free data retrieval call binding the contract method 0x220d7899. +// +// Solidity: function getInputSnarkBytes(uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 oldStateRoot, bytes32 newStateRoot) view returns(bytes) +func (_Polygonzkevm *PolygonzkevmSession) GetInputSnarkBytes(initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, oldStateRoot [32]byte, newStateRoot [32]byte) ([]byte, error) { + return _Polygonzkevm.Contract.GetInputSnarkBytes(&_Polygonzkevm.CallOpts, initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot) +} + +// GetInputSnarkBytes is a free data retrieval call binding the contract method 0x220d7899. +// +// Solidity: function getInputSnarkBytes(uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 oldStateRoot, bytes32 newStateRoot) view returns(bytes) +func (_Polygonzkevm *PolygonzkevmCallerSession) GetInputSnarkBytes(initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, oldStateRoot [32]byte, newStateRoot [32]byte) ([]byte, error) { + return _Polygonzkevm.Contract.GetInputSnarkBytes(&_Polygonzkevm.CallOpts, initNumBatch, finalNewBatch, newLocalExitRoot, oldStateRoot, newStateRoot) +} + +// GetLastVerifiedBatch is a free data retrieval call binding the contract method 0xc0ed84e0. +// +// Solidity: function getLastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) GetLastVerifiedBatch(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "getLastVerifiedBatch") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// GetLastVerifiedBatch is a free data retrieval call binding the contract method 0xc0ed84e0. +// +// Solidity: function getLastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) GetLastVerifiedBatch() (uint64, error) { + return _Polygonzkevm.Contract.GetLastVerifiedBatch(&_Polygonzkevm.CallOpts) +} + +// GetLastVerifiedBatch is a free data retrieval call binding the contract method 0xc0ed84e0. +// +// Solidity: function getLastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) GetLastVerifiedBatch() (uint64, error) { + return _Polygonzkevm.Contract.GetLastVerifiedBatch(&_Polygonzkevm.CallOpts) +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) GlobalExitRootManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "globalExitRootManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) GlobalExitRootManager() (common.Address, error) { + return _Polygonzkevm.Contract.GlobalExitRootManager(&_Polygonzkevm.CallOpts) +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) GlobalExitRootManager() (common.Address, error) { + return _Polygonzkevm.Contract.GlobalExitRootManager(&_Polygonzkevm.CallOpts) +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevm *PolygonzkevmCaller) IsEmergencyState(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "isEmergencyState") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevm *PolygonzkevmSession) IsEmergencyState() (bool, error) { + return _Polygonzkevm.Contract.IsEmergencyState(&_Polygonzkevm.CallOpts) +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevm *PolygonzkevmCallerSession) IsEmergencyState() (bool, error) { + return _Polygonzkevm.Contract.IsEmergencyState(&_Polygonzkevm.CallOpts) +} + +// IsForcedBatchDisallowed is a free data retrieval call binding the contract method 0xed6b0104. +// +// Solidity: function isForcedBatchDisallowed() view returns(bool) +func (_Polygonzkevm *PolygonzkevmCaller) IsForcedBatchDisallowed(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "isForcedBatchDisallowed") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsForcedBatchDisallowed is a free data retrieval call binding the contract method 0xed6b0104. +// +// Solidity: function isForcedBatchDisallowed() view returns(bool) +func (_Polygonzkevm *PolygonzkevmSession) IsForcedBatchDisallowed() (bool, error) { + return _Polygonzkevm.Contract.IsForcedBatchDisallowed(&_Polygonzkevm.CallOpts) +} + +// IsForcedBatchDisallowed is a free data retrieval call binding the contract method 0xed6b0104. +// +// Solidity: function isForcedBatchDisallowed() view returns(bool) +func (_Polygonzkevm *PolygonzkevmCallerSession) IsForcedBatchDisallowed() (bool, error) { + return _Polygonzkevm.Contract.IsForcedBatchDisallowed(&_Polygonzkevm.CallOpts) +} + +// IsPendingStateConsolidable is a free data retrieval call binding the contract method 0x383b3be8. +// +// Solidity: function isPendingStateConsolidable(uint64 pendingStateNum) view returns(bool) +func (_Polygonzkevm *PolygonzkevmCaller) IsPendingStateConsolidable(opts *bind.CallOpts, pendingStateNum uint64) (bool, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "isPendingStateConsolidable", pendingStateNum) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsPendingStateConsolidable is a free data retrieval call binding the contract method 0x383b3be8. +// +// Solidity: function isPendingStateConsolidable(uint64 pendingStateNum) view returns(bool) +func (_Polygonzkevm *PolygonzkevmSession) IsPendingStateConsolidable(pendingStateNum uint64) (bool, error) { + return _Polygonzkevm.Contract.IsPendingStateConsolidable(&_Polygonzkevm.CallOpts, pendingStateNum) +} + +// IsPendingStateConsolidable is a free data retrieval call binding the contract method 0x383b3be8. +// +// Solidity: function isPendingStateConsolidable(uint64 pendingStateNum) view returns(bool) +func (_Polygonzkevm *PolygonzkevmCallerSession) IsPendingStateConsolidable(pendingStateNum uint64) (bool, error) { + return _Polygonzkevm.Contract.IsPendingStateConsolidable(&_Polygonzkevm.CallOpts, pendingStateNum) +} + +// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. +// +// Solidity: function lastBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastBatchSequenced(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastBatchSequenced") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. +// +// Solidity: function lastBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastBatchSequenced() (uint64, error) { + return _Polygonzkevm.Contract.LastBatchSequenced(&_Polygonzkevm.CallOpts) +} + +// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. +// +// Solidity: function lastBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastBatchSequenced() (uint64, error) { + return _Polygonzkevm.Contract.LastBatchSequenced(&_Polygonzkevm.CallOpts) +} + +// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. +// +// Solidity: function lastForceBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastForceBatch(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastForceBatch") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. +// +// Solidity: function lastForceBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastForceBatch() (uint64, error) { + return _Polygonzkevm.Contract.LastForceBatch(&_Polygonzkevm.CallOpts) +} + +// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. +// +// Solidity: function lastForceBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastForceBatch() (uint64, error) { + return _Polygonzkevm.Contract.LastForceBatch(&_Polygonzkevm.CallOpts) +} + +// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. +// +// Solidity: function lastForceBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastForceBatchSequenced(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastForceBatchSequenced") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. +// +// Solidity: function lastForceBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastForceBatchSequenced() (uint64, error) { + return _Polygonzkevm.Contract.LastForceBatchSequenced(&_Polygonzkevm.CallOpts) +} + +// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. +// +// Solidity: function lastForceBatchSequenced() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastForceBatchSequenced() (uint64, error) { + return _Polygonzkevm.Contract.LastForceBatchSequenced(&_Polygonzkevm.CallOpts) +} + +// LastPendingState is a free data retrieval call binding the contract method 0x458c0477. +// +// Solidity: function lastPendingState() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastPendingState(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastPendingState") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastPendingState is a free data retrieval call binding the contract method 0x458c0477. +// +// Solidity: function lastPendingState() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastPendingState() (uint64, error) { + return _Polygonzkevm.Contract.LastPendingState(&_Polygonzkevm.CallOpts) +} + +// LastPendingState is a free data retrieval call binding the contract method 0x458c0477. +// +// Solidity: function lastPendingState() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastPendingState() (uint64, error) { + return _Polygonzkevm.Contract.LastPendingState(&_Polygonzkevm.CallOpts) +} + +// LastPendingStateConsolidated is a free data retrieval call binding the contract method 0x4a1a89a7. +// +// Solidity: function lastPendingStateConsolidated() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastPendingStateConsolidated(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastPendingStateConsolidated") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastPendingStateConsolidated is a free data retrieval call binding the contract method 0x4a1a89a7. +// +// Solidity: function lastPendingStateConsolidated() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastPendingStateConsolidated() (uint64, error) { + return _Polygonzkevm.Contract.LastPendingStateConsolidated(&_Polygonzkevm.CallOpts) +} + +// LastPendingStateConsolidated is a free data retrieval call binding the contract method 0x4a1a89a7. +// +// Solidity: function lastPendingStateConsolidated() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastPendingStateConsolidated() (uint64, error) { + return _Polygonzkevm.Contract.LastPendingStateConsolidated(&_Polygonzkevm.CallOpts) +} + +// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. +// +// Solidity: function lastTimestamp() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastTimestamp(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastTimestamp") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. +// +// Solidity: function lastTimestamp() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastTimestamp() (uint64, error) { + return _Polygonzkevm.Contract.LastTimestamp(&_Polygonzkevm.CallOpts) +} + +// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. +// +// Solidity: function lastTimestamp() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastTimestamp() (uint64, error) { + return _Polygonzkevm.Contract.LastTimestamp(&_Polygonzkevm.CallOpts) +} + +// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. +// +// Solidity: function lastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) LastVerifiedBatch(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "lastVerifiedBatch") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. +// +// Solidity: function lastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) LastVerifiedBatch() (uint64, error) { + return _Polygonzkevm.Contract.LastVerifiedBatch(&_Polygonzkevm.CallOpts) +} + +// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. +// +// Solidity: function lastVerifiedBatch() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) LastVerifiedBatch() (uint64, error) { + return _Polygonzkevm.Contract.LastVerifiedBatch(&_Polygonzkevm.CallOpts) +} + +// Matic is a free data retrieval call binding the contract method 0xb6b0b097. +// +// Solidity: function matic() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) Matic(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "matic") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Matic is a free data retrieval call binding the contract method 0xb6b0b097. +// +// Solidity: function matic() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) Matic() (common.Address, error) { + return _Polygonzkevm.Contract.Matic(&_Polygonzkevm.CallOpts) +} + +// Matic is a free data retrieval call binding the contract method 0xb6b0b097. +// +// Solidity: function matic() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) Matic() (common.Address, error) { + return _Polygonzkevm.Contract.Matic(&_Polygonzkevm.CallOpts) +} + +// MultiplierBatchFee is a free data retrieval call binding the contract method 0xafd23cbe. +// +// Solidity: function multiplierBatchFee() view returns(uint16) +func (_Polygonzkevm *PolygonzkevmCaller) MultiplierBatchFee(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "multiplierBatchFee") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// MultiplierBatchFee is a free data retrieval call binding the contract method 0xafd23cbe. +// +// Solidity: function multiplierBatchFee() view returns(uint16) +func (_Polygonzkevm *PolygonzkevmSession) MultiplierBatchFee() (uint16, error) { + return _Polygonzkevm.Contract.MultiplierBatchFee(&_Polygonzkevm.CallOpts) +} + +// MultiplierBatchFee is a free data retrieval call binding the contract method 0xafd23cbe. +// +// Solidity: function multiplierBatchFee() view returns(uint16) +func (_Polygonzkevm *PolygonzkevmCallerSession) MultiplierBatchFee() (uint16, error) { + return _Polygonzkevm.Contract.MultiplierBatchFee(&_Polygonzkevm.CallOpts) +} + +// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. +// +// Solidity: function networkName() view returns(string) +func (_Polygonzkevm *PolygonzkevmCaller) NetworkName(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "networkName") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. +// +// Solidity: function networkName() view returns(string) +func (_Polygonzkevm *PolygonzkevmSession) NetworkName() (string, error) { + return _Polygonzkevm.Contract.NetworkName(&_Polygonzkevm.CallOpts) +} + +// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. +// +// Solidity: function networkName() view returns(string) +func (_Polygonzkevm *PolygonzkevmCallerSession) NetworkName() (string, error) { + return _Polygonzkevm.Contract.NetworkName(&_Polygonzkevm.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.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 (_Polygonzkevm *PolygonzkevmSession) Owner() (common.Address, error) { + return _Polygonzkevm.Contract.Owner(&_Polygonzkevm.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) Owner() (common.Address, error) { + return _Polygonzkevm.Contract.Owner(&_Polygonzkevm.CallOpts) +} + +// PendingAdmin is a free data retrieval call binding the contract method 0x26782247. +// +// Solidity: function pendingAdmin() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) PendingAdmin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "pendingAdmin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// PendingAdmin is a free data retrieval call binding the contract method 0x26782247. +// +// Solidity: function pendingAdmin() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) PendingAdmin() (common.Address, error) { + return _Polygonzkevm.Contract.PendingAdmin(&_Polygonzkevm.CallOpts) +} + +// PendingAdmin is a free data retrieval call binding the contract method 0x26782247. +// +// Solidity: function pendingAdmin() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) PendingAdmin() (common.Address, error) { + return _Polygonzkevm.Contract.PendingAdmin(&_Polygonzkevm.CallOpts) +} + +// PendingStateTimeout is a free data retrieval call binding the contract method 0xd939b315. +// +// Solidity: function pendingStateTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) PendingStateTimeout(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "pendingStateTimeout") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// PendingStateTimeout is a free data retrieval call binding the contract method 0xd939b315. +// +// Solidity: function pendingStateTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) PendingStateTimeout() (uint64, error) { + return _Polygonzkevm.Contract.PendingStateTimeout(&_Polygonzkevm.CallOpts) +} + +// PendingStateTimeout is a free data retrieval call binding the contract method 0xd939b315. +// +// Solidity: function pendingStateTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) PendingStateTimeout() (uint64, error) { + return _Polygonzkevm.Contract.PendingStateTimeout(&_Polygonzkevm.CallOpts) +} + +// PendingStateTransitions is a free data retrieval call binding the contract method 0x837a4738. +// +// Solidity: function pendingStateTransitions(uint256 ) view returns(uint64 timestamp, uint64 lastVerifiedBatch, bytes32 exitRoot, bytes32 stateRoot) +func (_Polygonzkevm *PolygonzkevmCaller) PendingStateTransitions(opts *bind.CallOpts, arg0 *big.Int) (struct { + Timestamp uint64 + LastVerifiedBatch uint64 + ExitRoot [32]byte + StateRoot [32]byte +}, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "pendingStateTransitions", arg0) + + outstruct := new(struct { + Timestamp uint64 + LastVerifiedBatch uint64 + ExitRoot [32]byte + StateRoot [32]byte + }) + if err != nil { + return *outstruct, err + } + + outstruct.Timestamp = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.LastVerifiedBatch = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.ExitRoot = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + outstruct.StateRoot = *abi.ConvertType(out[3], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +// PendingStateTransitions is a free data retrieval call binding the contract method 0x837a4738. +// +// Solidity: function pendingStateTransitions(uint256 ) view returns(uint64 timestamp, uint64 lastVerifiedBatch, bytes32 exitRoot, bytes32 stateRoot) +func (_Polygonzkevm *PolygonzkevmSession) PendingStateTransitions(arg0 *big.Int) (struct { + Timestamp uint64 + LastVerifiedBatch uint64 + ExitRoot [32]byte + StateRoot [32]byte +}, error) { + return _Polygonzkevm.Contract.PendingStateTransitions(&_Polygonzkevm.CallOpts, arg0) +} + +// PendingStateTransitions is a free data retrieval call binding the contract method 0x837a4738. +// +// Solidity: function pendingStateTransitions(uint256 ) view returns(uint64 timestamp, uint64 lastVerifiedBatch, bytes32 exitRoot, bytes32 stateRoot) +func (_Polygonzkevm *PolygonzkevmCallerSession) PendingStateTransitions(arg0 *big.Int) (struct { + Timestamp uint64 + LastVerifiedBatch uint64 + ExitRoot [32]byte + StateRoot [32]byte +}, error) { + return _Polygonzkevm.Contract.PendingStateTransitions(&_Polygonzkevm.CallOpts, arg0) +} + +// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. +// +// Solidity: function rollupVerifier() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) RollupVerifier(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "rollupVerifier") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. +// +// Solidity: function rollupVerifier() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) RollupVerifier() (common.Address, error) { + return _Polygonzkevm.Contract.RollupVerifier(&_Polygonzkevm.CallOpts) +} + +// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. +// +// Solidity: function rollupVerifier() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) RollupVerifier() (common.Address, error) { + return _Polygonzkevm.Contract.RollupVerifier(&_Polygonzkevm.CallOpts) +} + +// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. +// +// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 accInputHash, uint64 sequencedTimestamp, uint64 previousLastBatchSequenced) +func (_Polygonzkevm *PolygonzkevmCaller) SequencedBatches(opts *bind.CallOpts, arg0 uint64) (struct { + AccInputHash [32]byte + SequencedTimestamp uint64 + PreviousLastBatchSequenced uint64 +}, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "sequencedBatches", arg0) + + outstruct := new(struct { + AccInputHash [32]byte + SequencedTimestamp uint64 + PreviousLastBatchSequenced uint64 + }) + if err != nil { + return *outstruct, err + } + + outstruct.AccInputHash = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.SequencedTimestamp = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.PreviousLastBatchSequenced = *abi.ConvertType(out[2], new(uint64)).(*uint64) + + return *outstruct, err + +} + +// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. +// +// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 accInputHash, uint64 sequencedTimestamp, uint64 previousLastBatchSequenced) +func (_Polygonzkevm *PolygonzkevmSession) SequencedBatches(arg0 uint64) (struct { + AccInputHash [32]byte + SequencedTimestamp uint64 + PreviousLastBatchSequenced uint64 +}, error) { + return _Polygonzkevm.Contract.SequencedBatches(&_Polygonzkevm.CallOpts, arg0) +} + +// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. +// +// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 accInputHash, uint64 sequencedTimestamp, uint64 previousLastBatchSequenced) +func (_Polygonzkevm *PolygonzkevmCallerSession) SequencedBatches(arg0 uint64) (struct { + AccInputHash [32]byte + SequencedTimestamp uint64 + PreviousLastBatchSequenced uint64 +}, error) { + return _Polygonzkevm.Contract.SequencedBatches(&_Polygonzkevm.CallOpts, arg0) +} + +// TrustedAggregator is a free data retrieval call binding the contract method 0x29878983. +// +// Solidity: function trustedAggregator() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) TrustedAggregator(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "trustedAggregator") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TrustedAggregator is a free data retrieval call binding the contract method 0x29878983. +// +// Solidity: function trustedAggregator() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) TrustedAggregator() (common.Address, error) { + return _Polygonzkevm.Contract.TrustedAggregator(&_Polygonzkevm.CallOpts) +} + +// TrustedAggregator is a free data retrieval call binding the contract method 0x29878983. +// +// Solidity: function trustedAggregator() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) TrustedAggregator() (common.Address, error) { + return _Polygonzkevm.Contract.TrustedAggregator(&_Polygonzkevm.CallOpts) +} + +// TrustedAggregatorTimeout is a free data retrieval call binding the contract method 0x841b24d7. +// +// Solidity: function trustedAggregatorTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) TrustedAggregatorTimeout(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "trustedAggregatorTimeout") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// TrustedAggregatorTimeout is a free data retrieval call binding the contract method 0x841b24d7. +// +// Solidity: function trustedAggregatorTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) TrustedAggregatorTimeout() (uint64, error) { + return _Polygonzkevm.Contract.TrustedAggregatorTimeout(&_Polygonzkevm.CallOpts) +} + +// TrustedAggregatorTimeout is a free data retrieval call binding the contract method 0x841b24d7. +// +// Solidity: function trustedAggregatorTimeout() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) TrustedAggregatorTimeout() (uint64, error) { + return _Polygonzkevm.Contract.TrustedAggregatorTimeout(&_Polygonzkevm.CallOpts) +} + +// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. +// +// Solidity: function trustedSequencer() view returns(address) +func (_Polygonzkevm *PolygonzkevmCaller) TrustedSequencer(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "trustedSequencer") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. +// +// Solidity: function trustedSequencer() view returns(address) +func (_Polygonzkevm *PolygonzkevmSession) TrustedSequencer() (common.Address, error) { + return _Polygonzkevm.Contract.TrustedSequencer(&_Polygonzkevm.CallOpts) +} + +// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. +// +// Solidity: function trustedSequencer() view returns(address) +func (_Polygonzkevm *PolygonzkevmCallerSession) TrustedSequencer() (common.Address, error) { + return _Polygonzkevm.Contract.TrustedSequencer(&_Polygonzkevm.CallOpts) +} + +// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. +// +// Solidity: function trustedSequencerURL() view returns(string) +func (_Polygonzkevm *PolygonzkevmCaller) TrustedSequencerURL(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "trustedSequencerURL") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. +// +// Solidity: function trustedSequencerURL() view returns(string) +func (_Polygonzkevm *PolygonzkevmSession) TrustedSequencerURL() (string, error) { + return _Polygonzkevm.Contract.TrustedSequencerURL(&_Polygonzkevm.CallOpts) +} + +// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. +// +// Solidity: function trustedSequencerURL() view returns(string) +func (_Polygonzkevm *PolygonzkevmCallerSession) TrustedSequencerURL() (string, error) { + return _Polygonzkevm.Contract.TrustedSequencerURL(&_Polygonzkevm.CallOpts) +} + +// VerifyBatchTimeTarget is a free data retrieval call binding the contract method 0x0a0d9fbe. +// +// Solidity: function verifyBatchTimeTarget() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCaller) VerifyBatchTimeTarget(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Polygonzkevm.contract.Call(opts, &out, "verifyBatchTimeTarget") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// VerifyBatchTimeTarget is a free data retrieval call binding the contract method 0x0a0d9fbe. +// +// Solidity: function verifyBatchTimeTarget() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmSession) VerifyBatchTimeTarget() (uint64, error) { + return _Polygonzkevm.Contract.VerifyBatchTimeTarget(&_Polygonzkevm.CallOpts) +} + +// VerifyBatchTimeTarget is a free data retrieval call binding the contract method 0x0a0d9fbe. +// +// Solidity: function verifyBatchTimeTarget() view returns(uint64) +func (_Polygonzkevm *PolygonzkevmCallerSession) VerifyBatchTimeTarget() (uint64, error) { + return _Polygonzkevm.Contract.VerifyBatchTimeTarget(&_Polygonzkevm.CallOpts) +} + +// AcceptAdminRole is a paid mutator transaction binding the contract method 0x8c3d7301. +// +// Solidity: function acceptAdminRole() returns() +func (_Polygonzkevm *PolygonzkevmTransactor) AcceptAdminRole(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "acceptAdminRole") +} + +// AcceptAdminRole is a paid mutator transaction binding the contract method 0x8c3d7301. +// +// Solidity: function acceptAdminRole() returns() +func (_Polygonzkevm *PolygonzkevmSession) AcceptAdminRole() (*types.Transaction, error) { + return _Polygonzkevm.Contract.AcceptAdminRole(&_Polygonzkevm.TransactOpts) +} + +// AcceptAdminRole is a paid mutator transaction binding the contract method 0x8c3d7301. +// +// Solidity: function acceptAdminRole() returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) AcceptAdminRole() (*types.Transaction, error) { + return _Polygonzkevm.Contract.AcceptAdminRole(&_Polygonzkevm.TransactOpts) +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x7215541a. +// +// Solidity: function activateEmergencyState(uint64 sequencedBatchNum) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) ActivateEmergencyState(opts *bind.TransactOpts, sequencedBatchNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "activateEmergencyState", sequencedBatchNum) +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x7215541a. +// +// Solidity: function activateEmergencyState(uint64 sequencedBatchNum) returns() +func (_Polygonzkevm *PolygonzkevmSession) ActivateEmergencyState(sequencedBatchNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ActivateEmergencyState(&_Polygonzkevm.TransactOpts, sequencedBatchNum) +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x7215541a. +// +// Solidity: function activateEmergencyState(uint64 sequencedBatchNum) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) ActivateEmergencyState(sequencedBatchNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ActivateEmergencyState(&_Polygonzkevm.TransactOpts, sequencedBatchNum) +} + +// ActivateForceBatches is a paid mutator transaction binding the contract method 0x5ec91958. +// +// Solidity: function activateForceBatches() returns() +func (_Polygonzkevm *PolygonzkevmTransactor) ActivateForceBatches(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "activateForceBatches") +} + +// ActivateForceBatches is a paid mutator transaction binding the contract method 0x5ec91958. +// +// Solidity: function activateForceBatches() returns() +func (_Polygonzkevm *PolygonzkevmSession) ActivateForceBatches() (*types.Transaction, error) { + return _Polygonzkevm.Contract.ActivateForceBatches(&_Polygonzkevm.TransactOpts) +} + +// ActivateForceBatches is a paid mutator transaction binding the contract method 0x5ec91958. +// +// Solidity: function activateForceBatches() returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) ActivateForceBatches() (*types.Transaction, error) { + return _Polygonzkevm.Contract.ActivateForceBatches(&_Polygonzkevm.TransactOpts) +} + +// ConsolidatePendingState is a paid mutator transaction binding the contract method 0x4a910e6a. +// +// Solidity: function consolidatePendingState(uint64 pendingStateNum) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) ConsolidatePendingState(opts *bind.TransactOpts, pendingStateNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "consolidatePendingState", pendingStateNum) +} + +// ConsolidatePendingState is a paid mutator transaction binding the contract method 0x4a910e6a. +// +// Solidity: function consolidatePendingState(uint64 pendingStateNum) returns() +func (_Polygonzkevm *PolygonzkevmSession) ConsolidatePendingState(pendingStateNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ConsolidatePendingState(&_Polygonzkevm.TransactOpts, pendingStateNum) +} + +// ConsolidatePendingState is a paid mutator transaction binding the contract method 0x4a910e6a. +// +// Solidity: function consolidatePendingState(uint64 pendingStateNum) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) ConsolidatePendingState(pendingStateNum uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ConsolidatePendingState(&_Polygonzkevm.TransactOpts, pendingStateNum) +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevm *PolygonzkevmTransactor) DeactivateEmergencyState(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "deactivateEmergencyState") +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevm *PolygonzkevmSession) DeactivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevm.Contract.DeactivateEmergencyState(&_Polygonzkevm.TransactOpts) +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) DeactivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevm.Contract.DeactivateEmergencyState(&_Polygonzkevm.TransactOpts) +} + +// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. +// +// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) ForceBatch(opts *bind.TransactOpts, transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "forceBatch", transactions, maticAmount) +} + +// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. +// +// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() +func (_Polygonzkevm *PolygonzkevmSession) ForceBatch(transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ForceBatch(&_Polygonzkevm.TransactOpts, transactions, maticAmount) +} + +// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. +// +// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) ForceBatch(transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ForceBatch(&_Polygonzkevm.TransactOpts, transactions, maticAmount) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd2e129f9. +// +// Solidity: function initialize((address,address,uint64,address,uint64) initializePackedParameters, bytes32 genesisRoot, string _trustedSequencerURL, string _networkName, string _version) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) Initialize(opts *bind.TransactOpts, initializePackedParameters PolygonZkEVMInitializePackedParameters, genesisRoot [32]byte, _trustedSequencerURL string, _networkName string, _version string) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "initialize", initializePackedParameters, genesisRoot, _trustedSequencerURL, _networkName, _version) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd2e129f9. +// +// Solidity: function initialize((address,address,uint64,address,uint64) initializePackedParameters, bytes32 genesisRoot, string _trustedSequencerURL, string _networkName, string _version) returns() +func (_Polygonzkevm *PolygonzkevmSession) Initialize(initializePackedParameters PolygonZkEVMInitializePackedParameters, genesisRoot [32]byte, _trustedSequencerURL string, _networkName string, _version string) (*types.Transaction, error) { + return _Polygonzkevm.Contract.Initialize(&_Polygonzkevm.TransactOpts, initializePackedParameters, genesisRoot, _trustedSequencerURL, _networkName, _version) +} + +// Initialize is a paid mutator transaction binding the contract method 0xd2e129f9. +// +// Solidity: function initialize((address,address,uint64,address,uint64) initializePackedParameters, bytes32 genesisRoot, string _trustedSequencerURL, string _networkName, string _version) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) Initialize(initializePackedParameters PolygonZkEVMInitializePackedParameters, genesisRoot [32]byte, _trustedSequencerURL string, _networkName string, _version string) (*types.Transaction, error) { + return _Polygonzkevm.Contract.Initialize(&_Polygonzkevm.TransactOpts, initializePackedParameters, genesisRoot, _trustedSequencerURL, _networkName, _version) +} + +// OverridePendingState is a paid mutator transaction binding the contract method 0xe6ad707e. +// +// Solidity: function overridePendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) OverridePendingState(opts *bind.TransactOpts, initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "overridePendingState", initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// OverridePendingState is a paid mutator transaction binding the contract method 0xe6ad707e. +// +// Solidity: function overridePendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmSession) OverridePendingState(initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.OverridePendingState(&_Polygonzkevm.TransactOpts, initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// OverridePendingState is a paid mutator transaction binding the contract method 0xe6ad707e. +// +// Solidity: function overridePendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) OverridePendingState(initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.OverridePendingState(&_Polygonzkevm.TransactOpts, initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// ProveNonDeterministicPendingState is a paid mutator transaction binding the contract method 0x0808270c. +// +// Solidity: function proveNonDeterministicPendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) ProveNonDeterministicPendingState(opts *bind.TransactOpts, initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "proveNonDeterministicPendingState", initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// ProveNonDeterministicPendingState is a paid mutator transaction binding the contract method 0x0808270c. +// +// Solidity: function proveNonDeterministicPendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmSession) ProveNonDeterministicPendingState(initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ProveNonDeterministicPendingState(&_Polygonzkevm.TransactOpts, initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// ProveNonDeterministicPendingState is a paid mutator transaction binding the contract method 0x0808270c. +// +// Solidity: function proveNonDeterministicPendingState(uint64 initPendingStateNum, uint64 finalPendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) ProveNonDeterministicPendingState(initPendingStateNum uint64, finalPendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.ProveNonDeterministicPendingState(&_Polygonzkevm.TransactOpts, initPendingStateNum, finalPendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Polygonzkevm *PolygonzkevmTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Polygonzkevm *PolygonzkevmSession) RenounceOwnership() (*types.Transaction, error) { + return _Polygonzkevm.Contract.RenounceOwnership(&_Polygonzkevm.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _Polygonzkevm.Contract.RenounceOwnership(&_Polygonzkevm.TransactOpts) +} + +// SequenceBatches is a paid mutator transaction binding the contract method 0x5e9145c9. +// +// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64)[] batches, address l2Coinbase) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SequenceBatches(opts *bind.TransactOpts, batches []PolygonZkEVMBatchData, l2Coinbase common.Address) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "sequenceBatches", batches, l2Coinbase) +} + +// SequenceBatches is a paid mutator transaction binding the contract method 0x5e9145c9. +// +// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64)[] batches, address l2Coinbase) returns() +func (_Polygonzkevm *PolygonzkevmSession) SequenceBatches(batches []PolygonZkEVMBatchData, l2Coinbase common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SequenceBatches(&_Polygonzkevm.TransactOpts, batches, l2Coinbase) +} + +// SequenceBatches is a paid mutator transaction binding the contract method 0x5e9145c9. +// +// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64)[] batches, address l2Coinbase) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SequenceBatches(batches []PolygonZkEVMBatchData, l2Coinbase common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SequenceBatches(&_Polygonzkevm.TransactOpts, batches, l2Coinbase) +} + +// SequenceForceBatches is a paid mutator transaction binding the contract method 0xd8d1091b. +// +// Solidity: function sequenceForceBatches((bytes,bytes32,uint64)[] batches) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SequenceForceBatches(opts *bind.TransactOpts, batches []PolygonZkEVMForcedBatchData) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "sequenceForceBatches", batches) +} + +// SequenceForceBatches is a paid mutator transaction binding the contract method 0xd8d1091b. +// +// Solidity: function sequenceForceBatches((bytes,bytes32,uint64)[] batches) returns() +func (_Polygonzkevm *PolygonzkevmSession) SequenceForceBatches(batches []PolygonZkEVMForcedBatchData) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SequenceForceBatches(&_Polygonzkevm.TransactOpts, batches) +} + +// SequenceForceBatches is a paid mutator transaction binding the contract method 0xd8d1091b. +// +// Solidity: function sequenceForceBatches((bytes,bytes32,uint64)[] batches) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SequenceForceBatches(batches []PolygonZkEVMForcedBatchData) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SequenceForceBatches(&_Polygonzkevm.TransactOpts, batches) +} + +// SetForceBatchTimeout is a paid mutator transaction binding the contract method 0x4e487706. +// +// Solidity: function setForceBatchTimeout(uint64 newforceBatchTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetForceBatchTimeout(opts *bind.TransactOpts, newforceBatchTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setForceBatchTimeout", newforceBatchTimeout) +} + +// SetForceBatchTimeout is a paid mutator transaction binding the contract method 0x4e487706. +// +// Solidity: function setForceBatchTimeout(uint64 newforceBatchTimeout) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetForceBatchTimeout(newforceBatchTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetForceBatchTimeout(&_Polygonzkevm.TransactOpts, newforceBatchTimeout) +} + +// SetForceBatchTimeout is a paid mutator transaction binding the contract method 0x4e487706. +// +// Solidity: function setForceBatchTimeout(uint64 newforceBatchTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetForceBatchTimeout(newforceBatchTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetForceBatchTimeout(&_Polygonzkevm.TransactOpts, newforceBatchTimeout) +} + +// SetMultiplierBatchFee is a paid mutator transaction binding the contract method 0x1816b7e5. +// +// Solidity: function setMultiplierBatchFee(uint16 newMultiplierBatchFee) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetMultiplierBatchFee(opts *bind.TransactOpts, newMultiplierBatchFee uint16) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setMultiplierBatchFee", newMultiplierBatchFee) +} + +// SetMultiplierBatchFee is a paid mutator transaction binding the contract method 0x1816b7e5. +// +// Solidity: function setMultiplierBatchFee(uint16 newMultiplierBatchFee) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetMultiplierBatchFee(newMultiplierBatchFee uint16) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetMultiplierBatchFee(&_Polygonzkevm.TransactOpts, newMultiplierBatchFee) +} + +// SetMultiplierBatchFee is a paid mutator transaction binding the contract method 0x1816b7e5. +// +// Solidity: function setMultiplierBatchFee(uint16 newMultiplierBatchFee) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetMultiplierBatchFee(newMultiplierBatchFee uint16) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetMultiplierBatchFee(&_Polygonzkevm.TransactOpts, newMultiplierBatchFee) +} + +// SetPendingStateTimeout is a paid mutator transaction binding the contract method 0x9c9f3dfe. +// +// Solidity: function setPendingStateTimeout(uint64 newPendingStateTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetPendingStateTimeout(opts *bind.TransactOpts, newPendingStateTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setPendingStateTimeout", newPendingStateTimeout) +} + +// SetPendingStateTimeout is a paid mutator transaction binding the contract method 0x9c9f3dfe. +// +// Solidity: function setPendingStateTimeout(uint64 newPendingStateTimeout) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetPendingStateTimeout(newPendingStateTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetPendingStateTimeout(&_Polygonzkevm.TransactOpts, newPendingStateTimeout) +} + +// SetPendingStateTimeout is a paid mutator transaction binding the contract method 0x9c9f3dfe. +// +// Solidity: function setPendingStateTimeout(uint64 newPendingStateTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetPendingStateTimeout(newPendingStateTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetPendingStateTimeout(&_Polygonzkevm.TransactOpts, newPendingStateTimeout) +} + +// SetTrustedAggregator is a paid mutator transaction binding the contract method 0xf14916d6. +// +// Solidity: function setTrustedAggregator(address newTrustedAggregator) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetTrustedAggregator(opts *bind.TransactOpts, newTrustedAggregator common.Address) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setTrustedAggregator", newTrustedAggregator) +} + +// SetTrustedAggregator is a paid mutator transaction binding the contract method 0xf14916d6. +// +// Solidity: function setTrustedAggregator(address newTrustedAggregator) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetTrustedAggregator(newTrustedAggregator common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedAggregator(&_Polygonzkevm.TransactOpts, newTrustedAggregator) +} + +// SetTrustedAggregator is a paid mutator transaction binding the contract method 0xf14916d6. +// +// Solidity: function setTrustedAggregator(address newTrustedAggregator) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetTrustedAggregator(newTrustedAggregator common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedAggregator(&_Polygonzkevm.TransactOpts, newTrustedAggregator) +} + +// SetTrustedAggregatorTimeout is a paid mutator transaction binding the contract method 0x394218e9. +// +// Solidity: function setTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetTrustedAggregatorTimeout(opts *bind.TransactOpts, newTrustedAggregatorTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setTrustedAggregatorTimeout", newTrustedAggregatorTimeout) +} + +// SetTrustedAggregatorTimeout is a paid mutator transaction binding the contract method 0x394218e9. +// +// Solidity: function setTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetTrustedAggregatorTimeout(newTrustedAggregatorTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedAggregatorTimeout(&_Polygonzkevm.TransactOpts, newTrustedAggregatorTimeout) +} + +// SetTrustedAggregatorTimeout is a paid mutator transaction binding the contract method 0x394218e9. +// +// Solidity: function setTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetTrustedAggregatorTimeout(newTrustedAggregatorTimeout uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedAggregatorTimeout(&_Polygonzkevm.TransactOpts, newTrustedAggregatorTimeout) +} + +// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. +// +// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetTrustedSequencer(opts *bind.TransactOpts, newTrustedSequencer common.Address) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setTrustedSequencer", newTrustedSequencer) +} + +// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. +// +// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetTrustedSequencer(newTrustedSequencer common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedSequencer(&_Polygonzkevm.TransactOpts, newTrustedSequencer) +} + +// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. +// +// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetTrustedSequencer(newTrustedSequencer common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedSequencer(&_Polygonzkevm.TransactOpts, newTrustedSequencer) +} + +// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. +// +// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetTrustedSequencerURL(opts *bind.TransactOpts, newTrustedSequencerURL string) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setTrustedSequencerURL", newTrustedSequencerURL) +} + +// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. +// +// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetTrustedSequencerURL(newTrustedSequencerURL string) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedSequencerURL(&_Polygonzkevm.TransactOpts, newTrustedSequencerURL) +} + +// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. +// +// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetTrustedSequencerURL(newTrustedSequencerURL string) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetTrustedSequencerURL(&_Polygonzkevm.TransactOpts, newTrustedSequencerURL) +} + +// SetVerifyBatchTimeTarget is a paid mutator transaction binding the contract method 0xa066215c. +// +// Solidity: function setVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) SetVerifyBatchTimeTarget(opts *bind.TransactOpts, newVerifyBatchTimeTarget uint64) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "setVerifyBatchTimeTarget", newVerifyBatchTimeTarget) +} + +// SetVerifyBatchTimeTarget is a paid mutator transaction binding the contract method 0xa066215c. +// +// Solidity: function setVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) returns() +func (_Polygonzkevm *PolygonzkevmSession) SetVerifyBatchTimeTarget(newVerifyBatchTimeTarget uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetVerifyBatchTimeTarget(&_Polygonzkevm.TransactOpts, newVerifyBatchTimeTarget) +} + +// SetVerifyBatchTimeTarget is a paid mutator transaction binding the contract method 0xa066215c. +// +// Solidity: function setVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) SetVerifyBatchTimeTarget(newVerifyBatchTimeTarget uint64) (*types.Transaction, error) { + return _Polygonzkevm.Contract.SetVerifyBatchTimeTarget(&_Polygonzkevm.TransactOpts, newVerifyBatchTimeTarget) +} + +// TransferAdminRole is a paid mutator transaction binding the contract method 0xada8f919. +// +// Solidity: function transferAdminRole(address newPendingAdmin) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) TransferAdminRole(opts *bind.TransactOpts, newPendingAdmin common.Address) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "transferAdminRole", newPendingAdmin) +} + +// TransferAdminRole is a paid mutator transaction binding the contract method 0xada8f919. +// +// Solidity: function transferAdminRole(address newPendingAdmin) returns() +func (_Polygonzkevm *PolygonzkevmSession) TransferAdminRole(newPendingAdmin common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.TransferAdminRole(&_Polygonzkevm.TransactOpts, newPendingAdmin) +} + +// TransferAdminRole is a paid mutator transaction binding the contract method 0xada8f919. +// +// Solidity: function transferAdminRole(address newPendingAdmin) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) TransferAdminRole(newPendingAdmin common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.TransferAdminRole(&_Polygonzkevm.TransactOpts, newPendingAdmin) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Polygonzkevm *PolygonzkevmSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.TransferOwnership(&_Polygonzkevm.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _Polygonzkevm.Contract.TransferOwnership(&_Polygonzkevm.TransactOpts, newOwner) +} + +// VerifyBatches is a paid mutator transaction binding the contract method 0x4fd70464. +// +// Solidity: function verifyBatches(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) VerifyBatches(opts *bind.TransactOpts, pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "verifyBatches", pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// VerifyBatches is a paid mutator transaction binding the contract method 0x4fd70464. +// +// Solidity: function verifyBatches(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmSession) VerifyBatches(pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.VerifyBatches(&_Polygonzkevm.TransactOpts, pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// VerifyBatches is a paid mutator transaction binding the contract method 0x4fd70464. +// +// Solidity: function verifyBatches(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) VerifyBatches(pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.VerifyBatches(&_Polygonzkevm.TransactOpts, pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// VerifyBatchesTrustedAggregator is a paid mutator transaction binding the contract method 0xa50a164b. +// +// Solidity: function verifyBatchesTrustedAggregator(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactor) VerifyBatchesTrustedAggregator(opts *bind.TransactOpts, pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.contract.Transact(opts, "verifyBatchesTrustedAggregator", pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// VerifyBatchesTrustedAggregator is a paid mutator transaction binding the contract method 0xa50a164b. +// +// Solidity: function verifyBatchesTrustedAggregator(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmSession) VerifyBatchesTrustedAggregator(pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.VerifyBatchesTrustedAggregator(&_Polygonzkevm.TransactOpts, pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// VerifyBatchesTrustedAggregator is a paid mutator transaction binding the contract method 0xa50a164b. +// +// Solidity: function verifyBatchesTrustedAggregator(uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, bytes32 newStateRoot, bytes proof) returns() +func (_Polygonzkevm *PolygonzkevmTransactorSession) VerifyBatchesTrustedAggregator(pendingStateNum uint64, initNumBatch uint64, finalNewBatch uint64, newLocalExitRoot [32]byte, newStateRoot [32]byte, proof []byte) (*types.Transaction, error) { + return _Polygonzkevm.Contract.VerifyBatchesTrustedAggregator(&_Polygonzkevm.TransactOpts, pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, newStateRoot, proof) +} + +// PolygonzkevmAcceptAdminRoleIterator is returned from FilterAcceptAdminRole and is used to iterate over the raw logs and unpacked data for AcceptAdminRole events raised by the Polygonzkevm contract. +type PolygonzkevmAcceptAdminRoleIterator struct { + Event *PolygonzkevmAcceptAdminRole // 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 *PolygonzkevmAcceptAdminRoleIterator) 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(PolygonzkevmAcceptAdminRole) + 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(PolygonzkevmAcceptAdminRole) + 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 *PolygonzkevmAcceptAdminRoleIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmAcceptAdminRoleIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmAcceptAdminRole represents a AcceptAdminRole event raised by the Polygonzkevm contract. +type PolygonzkevmAcceptAdminRole struct { + NewAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAcceptAdminRole is a free log retrieval operation binding the contract event 0x056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e. +// +// Solidity: event AcceptAdminRole(address newAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterAcceptAdminRole(opts *bind.FilterOpts) (*PolygonzkevmAcceptAdminRoleIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "AcceptAdminRole") + if err != nil { + return nil, err + } + return &PolygonzkevmAcceptAdminRoleIterator{contract: _Polygonzkevm.contract, event: "AcceptAdminRole", logs: logs, sub: sub}, nil +} + +// WatchAcceptAdminRole is a free log subscription operation binding the contract event 0x056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e. +// +// Solidity: event AcceptAdminRole(address newAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchAcceptAdminRole(opts *bind.WatchOpts, sink chan<- *PolygonzkevmAcceptAdminRole) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "AcceptAdminRole") + 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(PolygonzkevmAcceptAdminRole) + if err := _Polygonzkevm.contract.UnpackLog(event, "AcceptAdminRole", 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 +} + +// ParseAcceptAdminRole is a log parse operation binding the contract event 0x056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e. +// +// Solidity: event AcceptAdminRole(address newAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseAcceptAdminRole(log types.Log) (*PolygonzkevmAcceptAdminRole, error) { + event := new(PolygonzkevmAcceptAdminRole) + if err := _Polygonzkevm.contract.UnpackLog(event, "AcceptAdminRole", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmActivateForceBatchesIterator is returned from FilterActivateForceBatches and is used to iterate over the raw logs and unpacked data for ActivateForceBatches events raised by the Polygonzkevm contract. +type PolygonzkevmActivateForceBatchesIterator struct { + Event *PolygonzkevmActivateForceBatches // 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 *PolygonzkevmActivateForceBatchesIterator) 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(PolygonzkevmActivateForceBatches) + 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(PolygonzkevmActivateForceBatches) + 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 *PolygonzkevmActivateForceBatchesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmActivateForceBatchesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmActivateForceBatches represents a ActivateForceBatches event raised by the Polygonzkevm contract. +type PolygonzkevmActivateForceBatches struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterActivateForceBatches is a free log retrieval operation binding the contract event 0x854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f. +// +// Solidity: event ActivateForceBatches() +func (_Polygonzkevm *PolygonzkevmFilterer) FilterActivateForceBatches(opts *bind.FilterOpts) (*PolygonzkevmActivateForceBatchesIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "ActivateForceBatches") + if err != nil { + return nil, err + } + return &PolygonzkevmActivateForceBatchesIterator{contract: _Polygonzkevm.contract, event: "ActivateForceBatches", logs: logs, sub: sub}, nil +} + +// WatchActivateForceBatches is a free log subscription operation binding the contract event 0x854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f. +// +// Solidity: event ActivateForceBatches() +func (_Polygonzkevm *PolygonzkevmFilterer) WatchActivateForceBatches(opts *bind.WatchOpts, sink chan<- *PolygonzkevmActivateForceBatches) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "ActivateForceBatches") + 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(PolygonzkevmActivateForceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "ActivateForceBatches", 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 +} + +// ParseActivateForceBatches is a log parse operation binding the contract event 0x854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f. +// +// Solidity: event ActivateForceBatches() +func (_Polygonzkevm *PolygonzkevmFilterer) ParseActivateForceBatches(log types.Log) (*PolygonzkevmActivateForceBatches, error) { + event := new(PolygonzkevmActivateForceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "ActivateForceBatches", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmConsolidatePendingStateIterator is returned from FilterConsolidatePendingState and is used to iterate over the raw logs and unpacked data for ConsolidatePendingState events raised by the Polygonzkevm contract. +type PolygonzkevmConsolidatePendingStateIterator struct { + Event *PolygonzkevmConsolidatePendingState // 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 *PolygonzkevmConsolidatePendingStateIterator) 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(PolygonzkevmConsolidatePendingState) + 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(PolygonzkevmConsolidatePendingState) + 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 *PolygonzkevmConsolidatePendingStateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmConsolidatePendingStateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmConsolidatePendingState represents a ConsolidatePendingState event raised by the Polygonzkevm contract. +type PolygonzkevmConsolidatePendingState struct { + NumBatch uint64 + StateRoot [32]byte + PendingStateNum uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConsolidatePendingState is a free log retrieval operation binding the contract event 0x328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e. +// +// Solidity: event ConsolidatePendingState(uint64 indexed numBatch, bytes32 stateRoot, uint64 indexed pendingStateNum) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterConsolidatePendingState(opts *bind.FilterOpts, numBatch []uint64, pendingStateNum []uint64) (*PolygonzkevmConsolidatePendingStateIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var pendingStateNumRule []interface{} + for _, pendingStateNumItem := range pendingStateNum { + pendingStateNumRule = append(pendingStateNumRule, pendingStateNumItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "ConsolidatePendingState", numBatchRule, pendingStateNumRule) + if err != nil { + return nil, err + } + return &PolygonzkevmConsolidatePendingStateIterator{contract: _Polygonzkevm.contract, event: "ConsolidatePendingState", logs: logs, sub: sub}, nil +} + +// WatchConsolidatePendingState is a free log subscription operation binding the contract event 0x328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e. +// +// Solidity: event ConsolidatePendingState(uint64 indexed numBatch, bytes32 stateRoot, uint64 indexed pendingStateNum) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchConsolidatePendingState(opts *bind.WatchOpts, sink chan<- *PolygonzkevmConsolidatePendingState, numBatch []uint64, pendingStateNum []uint64) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var pendingStateNumRule []interface{} + for _, pendingStateNumItem := range pendingStateNum { + pendingStateNumRule = append(pendingStateNumRule, pendingStateNumItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "ConsolidatePendingState", numBatchRule, pendingStateNumRule) + 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(PolygonzkevmConsolidatePendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "ConsolidatePendingState", 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 +} + +// ParseConsolidatePendingState is a log parse operation binding the contract event 0x328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e. +// +// Solidity: event ConsolidatePendingState(uint64 indexed numBatch, bytes32 stateRoot, uint64 indexed pendingStateNum) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseConsolidatePendingState(log types.Log) (*PolygonzkevmConsolidatePendingState, error) { + event := new(PolygonzkevmConsolidatePendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "ConsolidatePendingState", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmEmergencyStateActivatedIterator is returned from FilterEmergencyStateActivated and is used to iterate over the raw logs and unpacked data for EmergencyStateActivated events raised by the Polygonzkevm contract. +type PolygonzkevmEmergencyStateActivatedIterator struct { + Event *PolygonzkevmEmergencyStateActivated // 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 *PolygonzkevmEmergencyStateActivatedIterator) 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(PolygonzkevmEmergencyStateActivated) + 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(PolygonzkevmEmergencyStateActivated) + 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 *PolygonzkevmEmergencyStateActivatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmEmergencyStateActivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmEmergencyStateActivated represents a EmergencyStateActivated event raised by the Polygonzkevm contract. +type PolygonzkevmEmergencyStateActivated struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterEmergencyStateActivated is a free log retrieval operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevm *PolygonzkevmFilterer) FilterEmergencyStateActivated(opts *bind.FilterOpts) (*PolygonzkevmEmergencyStateActivatedIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "EmergencyStateActivated") + if err != nil { + return nil, err + } + return &PolygonzkevmEmergencyStateActivatedIterator{contract: _Polygonzkevm.contract, event: "EmergencyStateActivated", logs: logs, sub: sub}, nil +} + +// WatchEmergencyStateActivated is a free log subscription operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevm *PolygonzkevmFilterer) WatchEmergencyStateActivated(opts *bind.WatchOpts, sink chan<- *PolygonzkevmEmergencyStateActivated) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "EmergencyStateActivated") + 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(PolygonzkevmEmergencyStateActivated) + if err := _Polygonzkevm.contract.UnpackLog(event, "EmergencyStateActivated", 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 +} + +// ParseEmergencyStateActivated is a log parse operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevm *PolygonzkevmFilterer) ParseEmergencyStateActivated(log types.Log) (*PolygonzkevmEmergencyStateActivated, error) { + event := new(PolygonzkevmEmergencyStateActivated) + if err := _Polygonzkevm.contract.UnpackLog(event, "EmergencyStateActivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmEmergencyStateDeactivatedIterator is returned from FilterEmergencyStateDeactivated and is used to iterate over the raw logs and unpacked data for EmergencyStateDeactivated events raised by the Polygonzkevm contract. +type PolygonzkevmEmergencyStateDeactivatedIterator struct { + Event *PolygonzkevmEmergencyStateDeactivated // 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 *PolygonzkevmEmergencyStateDeactivatedIterator) 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(PolygonzkevmEmergencyStateDeactivated) + 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(PolygonzkevmEmergencyStateDeactivated) + 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 *PolygonzkevmEmergencyStateDeactivatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmEmergencyStateDeactivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmEmergencyStateDeactivated represents a EmergencyStateDeactivated event raised by the Polygonzkevm contract. +type PolygonzkevmEmergencyStateDeactivated struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterEmergencyStateDeactivated is a free log retrieval operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevm *PolygonzkevmFilterer) FilterEmergencyStateDeactivated(opts *bind.FilterOpts) (*PolygonzkevmEmergencyStateDeactivatedIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "EmergencyStateDeactivated") + if err != nil { + return nil, err + } + return &PolygonzkevmEmergencyStateDeactivatedIterator{contract: _Polygonzkevm.contract, event: "EmergencyStateDeactivated", logs: logs, sub: sub}, nil +} + +// WatchEmergencyStateDeactivated is a free log subscription operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevm *PolygonzkevmFilterer) WatchEmergencyStateDeactivated(opts *bind.WatchOpts, sink chan<- *PolygonzkevmEmergencyStateDeactivated) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "EmergencyStateDeactivated") + 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(PolygonzkevmEmergencyStateDeactivated) + if err := _Polygonzkevm.contract.UnpackLog(event, "EmergencyStateDeactivated", 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 +} + +// ParseEmergencyStateDeactivated is a log parse operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevm *PolygonzkevmFilterer) ParseEmergencyStateDeactivated(log types.Log) (*PolygonzkevmEmergencyStateDeactivated, error) { + event := new(PolygonzkevmEmergencyStateDeactivated) + if err := _Polygonzkevm.contract.UnpackLog(event, "EmergencyStateDeactivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmForceBatchIterator is returned from FilterForceBatch and is used to iterate over the raw logs and unpacked data for ForceBatch events raised by the Polygonzkevm contract. +type PolygonzkevmForceBatchIterator struct { + Event *PolygonzkevmForceBatch // 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 *PolygonzkevmForceBatchIterator) 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(PolygonzkevmForceBatch) + 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(PolygonzkevmForceBatch) + 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 *PolygonzkevmForceBatchIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmForceBatchIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmForceBatch represents a ForceBatch event raised by the Polygonzkevm contract. +type PolygonzkevmForceBatch struct { + ForceBatchNum uint64 + LastGlobalExitRoot [32]byte + Sequencer common.Address + Transactions []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterForceBatch is a free log retrieval operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. +// +// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterForceBatch(opts *bind.FilterOpts, forceBatchNum []uint64) (*PolygonzkevmForceBatchIterator, error) { + + var forceBatchNumRule []interface{} + for _, forceBatchNumItem := range forceBatchNum { + forceBatchNumRule = append(forceBatchNumRule, forceBatchNumItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "ForceBatch", forceBatchNumRule) + if err != nil { + return nil, err + } + return &PolygonzkevmForceBatchIterator{contract: _Polygonzkevm.contract, event: "ForceBatch", logs: logs, sub: sub}, nil +} + +// WatchForceBatch is a free log subscription operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. +// +// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchForceBatch(opts *bind.WatchOpts, sink chan<- *PolygonzkevmForceBatch, forceBatchNum []uint64) (event.Subscription, error) { + + var forceBatchNumRule []interface{} + for _, forceBatchNumItem := range forceBatchNum { + forceBatchNumRule = append(forceBatchNumRule, forceBatchNumItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "ForceBatch", forceBatchNumRule) + 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(PolygonzkevmForceBatch) + if err := _Polygonzkevm.contract.UnpackLog(event, "ForceBatch", 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 +} + +// ParseForceBatch is a log parse operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. +// +// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseForceBatch(log types.Log) (*PolygonzkevmForceBatch, error) { + event := new(PolygonzkevmForceBatch) + if err := _Polygonzkevm.contract.UnpackLog(event, "ForceBatch", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Polygonzkevm contract. +type PolygonzkevmInitializedIterator struct { + Event *PolygonzkevmInitialized // 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 *PolygonzkevmInitializedIterator) 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(PolygonzkevmInitialized) + 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(PolygonzkevmInitialized) + 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 *PolygonzkevmInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmInitialized represents a Initialized event raised by the Polygonzkevm contract. +type PolygonzkevmInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterInitialized(opts *bind.FilterOpts) (*PolygonzkevmInitializedIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &PolygonzkevmInitializedIterator{contract: _Polygonzkevm.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *PolygonzkevmInitialized) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "Initialized") + 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(PolygonzkevmInitialized) + if err := _Polygonzkevm.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseInitialized(log types.Log) (*PolygonzkevmInitialized, error) { + event := new(PolygonzkevmInitialized) + if err := _Polygonzkevm.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmOverridePendingStateIterator is returned from FilterOverridePendingState and is used to iterate over the raw logs and unpacked data for OverridePendingState events raised by the Polygonzkevm contract. +type PolygonzkevmOverridePendingStateIterator struct { + Event *PolygonzkevmOverridePendingState // 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 *PolygonzkevmOverridePendingStateIterator) 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(PolygonzkevmOverridePendingState) + 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(PolygonzkevmOverridePendingState) + 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 *PolygonzkevmOverridePendingStateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmOverridePendingStateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmOverridePendingState represents a OverridePendingState event raised by the Polygonzkevm contract. +type PolygonzkevmOverridePendingState struct { + NumBatch uint64 + StateRoot [32]byte + Aggregator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOverridePendingState is a free log retrieval operation binding the contract event 0xcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf72. +// +// Solidity: event OverridePendingState(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterOverridePendingState(opts *bind.FilterOpts, numBatch []uint64, aggregator []common.Address) (*PolygonzkevmOverridePendingStateIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "OverridePendingState", numBatchRule, aggregatorRule) + if err != nil { + return nil, err + } + return &PolygonzkevmOverridePendingStateIterator{contract: _Polygonzkevm.contract, event: "OverridePendingState", logs: logs, sub: sub}, nil +} + +// WatchOverridePendingState is a free log subscription operation binding the contract event 0xcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf72. +// +// Solidity: event OverridePendingState(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchOverridePendingState(opts *bind.WatchOpts, sink chan<- *PolygonzkevmOverridePendingState, numBatch []uint64, aggregator []common.Address) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "OverridePendingState", numBatchRule, aggregatorRule) + 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(PolygonzkevmOverridePendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "OverridePendingState", 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 +} + +// ParseOverridePendingState is a log parse operation binding the contract event 0xcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf72. +// +// Solidity: event OverridePendingState(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseOverridePendingState(log types.Log) (*PolygonzkevmOverridePendingState, error) { + event := new(PolygonzkevmOverridePendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "OverridePendingState", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Polygonzkevm contract. +type PolygonzkevmOwnershipTransferredIterator struct { + Event *PolygonzkevmOwnershipTransferred // 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 *PolygonzkevmOwnershipTransferredIterator) 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(PolygonzkevmOwnershipTransferred) + 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(PolygonzkevmOwnershipTransferred) + 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 *PolygonzkevmOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmOwnershipTransferred represents a OwnershipTransferred event raised by the Polygonzkevm contract. +type PolygonzkevmOwnershipTransferred 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 (_Polygonzkevm *PolygonzkevmFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*PolygonzkevmOwnershipTransferredIterator, 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 := _Polygonzkevm.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &PolygonzkevmOwnershipTransferredIterator{contract: _Polygonzkevm.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 (_Polygonzkevm *PolygonzkevmFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PolygonzkevmOwnershipTransferred, 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 := _Polygonzkevm.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(PolygonzkevmOwnershipTransferred) + if err := _Polygonzkevm.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 (_Polygonzkevm *PolygonzkevmFilterer) ParseOwnershipTransferred(log types.Log) (*PolygonzkevmOwnershipTransferred, error) { + event := new(PolygonzkevmOwnershipTransferred) + if err := _Polygonzkevm.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmProveNonDeterministicPendingStateIterator is returned from FilterProveNonDeterministicPendingState and is used to iterate over the raw logs and unpacked data for ProveNonDeterministicPendingState events raised by the Polygonzkevm contract. +type PolygonzkevmProveNonDeterministicPendingStateIterator struct { + Event *PolygonzkevmProveNonDeterministicPendingState // 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 *PolygonzkevmProveNonDeterministicPendingStateIterator) 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(PolygonzkevmProveNonDeterministicPendingState) + 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(PolygonzkevmProveNonDeterministicPendingState) + 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 *PolygonzkevmProveNonDeterministicPendingStateIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmProveNonDeterministicPendingStateIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmProveNonDeterministicPendingState represents a ProveNonDeterministicPendingState event raised by the Polygonzkevm contract. +type PolygonzkevmProveNonDeterministicPendingState struct { + StoredStateRoot [32]byte + ProvedStateRoot [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterProveNonDeterministicPendingState is a free log retrieval operation binding the contract event 0x1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010. +// +// Solidity: event ProveNonDeterministicPendingState(bytes32 storedStateRoot, bytes32 provedStateRoot) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterProveNonDeterministicPendingState(opts *bind.FilterOpts) (*PolygonzkevmProveNonDeterministicPendingStateIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "ProveNonDeterministicPendingState") + if err != nil { + return nil, err + } + return &PolygonzkevmProveNonDeterministicPendingStateIterator{contract: _Polygonzkevm.contract, event: "ProveNonDeterministicPendingState", logs: logs, sub: sub}, nil +} + +// WatchProveNonDeterministicPendingState is a free log subscription operation binding the contract event 0x1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010. +// +// Solidity: event ProveNonDeterministicPendingState(bytes32 storedStateRoot, bytes32 provedStateRoot) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchProveNonDeterministicPendingState(opts *bind.WatchOpts, sink chan<- *PolygonzkevmProveNonDeterministicPendingState) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "ProveNonDeterministicPendingState") + 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(PolygonzkevmProveNonDeterministicPendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "ProveNonDeterministicPendingState", 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 +} + +// ParseProveNonDeterministicPendingState is a log parse operation binding the contract event 0x1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010. +// +// Solidity: event ProveNonDeterministicPendingState(bytes32 storedStateRoot, bytes32 provedStateRoot) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseProveNonDeterministicPendingState(log types.Log) (*PolygonzkevmProveNonDeterministicPendingState, error) { + event := new(PolygonzkevmProveNonDeterministicPendingState) + if err := _Polygonzkevm.contract.UnpackLog(event, "ProveNonDeterministicPendingState", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSequenceBatchesIterator is returned from FilterSequenceBatches and is used to iterate over the raw logs and unpacked data for SequenceBatches events raised by the Polygonzkevm contract. +type PolygonzkevmSequenceBatchesIterator struct { + Event *PolygonzkevmSequenceBatches // 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 *PolygonzkevmSequenceBatchesIterator) 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(PolygonzkevmSequenceBatches) + 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(PolygonzkevmSequenceBatches) + 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 *PolygonzkevmSequenceBatchesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSequenceBatchesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSequenceBatches represents a SequenceBatches event raised by the Polygonzkevm contract. +type PolygonzkevmSequenceBatches struct { + NumBatch uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSequenceBatches is a free log retrieval operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. +// +// Solidity: event SequenceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSequenceBatches(opts *bind.FilterOpts, numBatch []uint64) (*PolygonzkevmSequenceBatchesIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SequenceBatches", numBatchRule) + if err != nil { + return nil, err + } + return &PolygonzkevmSequenceBatchesIterator{contract: _Polygonzkevm.contract, event: "SequenceBatches", logs: logs, sub: sub}, nil +} + +// WatchSequenceBatches is a free log subscription operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. +// +// Solidity: event SequenceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSequenceBatches(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSequenceBatches, numBatch []uint64) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SequenceBatches", numBatchRule) + 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(PolygonzkevmSequenceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "SequenceBatches", 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 +} + +// ParseSequenceBatches is a log parse operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. +// +// Solidity: event SequenceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSequenceBatches(log types.Log) (*PolygonzkevmSequenceBatches, error) { + event := new(PolygonzkevmSequenceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "SequenceBatches", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSequenceForceBatchesIterator is returned from FilterSequenceForceBatches and is used to iterate over the raw logs and unpacked data for SequenceForceBatches events raised by the Polygonzkevm contract. +type PolygonzkevmSequenceForceBatchesIterator struct { + Event *PolygonzkevmSequenceForceBatches // 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 *PolygonzkevmSequenceForceBatchesIterator) 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(PolygonzkevmSequenceForceBatches) + 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(PolygonzkevmSequenceForceBatches) + 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 *PolygonzkevmSequenceForceBatchesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSequenceForceBatchesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSequenceForceBatches represents a SequenceForceBatches event raised by the Polygonzkevm contract. +type PolygonzkevmSequenceForceBatches struct { + NumBatch uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSequenceForceBatches is a free log retrieval operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. +// +// Solidity: event SequenceForceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSequenceForceBatches(opts *bind.FilterOpts, numBatch []uint64) (*PolygonzkevmSequenceForceBatchesIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SequenceForceBatches", numBatchRule) + if err != nil { + return nil, err + } + return &PolygonzkevmSequenceForceBatchesIterator{contract: _Polygonzkevm.contract, event: "SequenceForceBatches", logs: logs, sub: sub}, nil +} + +// WatchSequenceForceBatches is a free log subscription operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. +// +// Solidity: event SequenceForceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSequenceForceBatches(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSequenceForceBatches, numBatch []uint64) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SequenceForceBatches", numBatchRule) + 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(PolygonzkevmSequenceForceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "SequenceForceBatches", 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 +} + +// ParseSequenceForceBatches is a log parse operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. +// +// Solidity: event SequenceForceBatches(uint64 indexed numBatch) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSequenceForceBatches(log types.Log) (*PolygonzkevmSequenceForceBatches, error) { + event := new(PolygonzkevmSequenceForceBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "SequenceForceBatches", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetForceBatchTimeoutIterator is returned from FilterSetForceBatchTimeout and is used to iterate over the raw logs and unpacked data for SetForceBatchTimeout events raised by the Polygonzkevm contract. +type PolygonzkevmSetForceBatchTimeoutIterator struct { + Event *PolygonzkevmSetForceBatchTimeout // 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 *PolygonzkevmSetForceBatchTimeoutIterator) 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(PolygonzkevmSetForceBatchTimeout) + 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(PolygonzkevmSetForceBatchTimeout) + 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 *PolygonzkevmSetForceBatchTimeoutIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetForceBatchTimeoutIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetForceBatchTimeout represents a SetForceBatchTimeout event raised by the Polygonzkevm contract. +type PolygonzkevmSetForceBatchTimeout struct { + NewforceBatchTimeout uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetForceBatchTimeout is a free log retrieval operation binding the contract event 0xa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b. +// +// Solidity: event SetForceBatchTimeout(uint64 newforceBatchTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetForceBatchTimeout(opts *bind.FilterOpts) (*PolygonzkevmSetForceBatchTimeoutIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetForceBatchTimeout") + if err != nil { + return nil, err + } + return &PolygonzkevmSetForceBatchTimeoutIterator{contract: _Polygonzkevm.contract, event: "SetForceBatchTimeout", logs: logs, sub: sub}, nil +} + +// WatchSetForceBatchTimeout is a free log subscription operation binding the contract event 0xa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b. +// +// Solidity: event SetForceBatchTimeout(uint64 newforceBatchTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetForceBatchTimeout(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetForceBatchTimeout) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetForceBatchTimeout") + 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(PolygonzkevmSetForceBatchTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetForceBatchTimeout", 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 +} + +// ParseSetForceBatchTimeout is a log parse operation binding the contract event 0xa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b. +// +// Solidity: event SetForceBatchTimeout(uint64 newforceBatchTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetForceBatchTimeout(log types.Log) (*PolygonzkevmSetForceBatchTimeout, error) { + event := new(PolygonzkevmSetForceBatchTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetForceBatchTimeout", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetMultiplierBatchFeeIterator is returned from FilterSetMultiplierBatchFee and is used to iterate over the raw logs and unpacked data for SetMultiplierBatchFee events raised by the Polygonzkevm contract. +type PolygonzkevmSetMultiplierBatchFeeIterator struct { + Event *PolygonzkevmSetMultiplierBatchFee // 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 *PolygonzkevmSetMultiplierBatchFeeIterator) 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(PolygonzkevmSetMultiplierBatchFee) + 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(PolygonzkevmSetMultiplierBatchFee) + 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 *PolygonzkevmSetMultiplierBatchFeeIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetMultiplierBatchFeeIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetMultiplierBatchFee represents a SetMultiplierBatchFee event raised by the Polygonzkevm contract. +type PolygonzkevmSetMultiplierBatchFee struct { + NewMultiplierBatchFee uint16 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetMultiplierBatchFee is a free log retrieval operation binding the contract event 0x7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5. +// +// Solidity: event SetMultiplierBatchFee(uint16 newMultiplierBatchFee) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetMultiplierBatchFee(opts *bind.FilterOpts) (*PolygonzkevmSetMultiplierBatchFeeIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetMultiplierBatchFee") + if err != nil { + return nil, err + } + return &PolygonzkevmSetMultiplierBatchFeeIterator{contract: _Polygonzkevm.contract, event: "SetMultiplierBatchFee", logs: logs, sub: sub}, nil +} + +// WatchSetMultiplierBatchFee is a free log subscription operation binding the contract event 0x7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5. +// +// Solidity: event SetMultiplierBatchFee(uint16 newMultiplierBatchFee) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetMultiplierBatchFee(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetMultiplierBatchFee) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetMultiplierBatchFee") + 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(PolygonzkevmSetMultiplierBatchFee) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetMultiplierBatchFee", 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 +} + +// ParseSetMultiplierBatchFee is a log parse operation binding the contract event 0x7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5. +// +// Solidity: event SetMultiplierBatchFee(uint16 newMultiplierBatchFee) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetMultiplierBatchFee(log types.Log) (*PolygonzkevmSetMultiplierBatchFee, error) { + event := new(PolygonzkevmSetMultiplierBatchFee) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetMultiplierBatchFee", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetPendingStateTimeoutIterator is returned from FilterSetPendingStateTimeout and is used to iterate over the raw logs and unpacked data for SetPendingStateTimeout events raised by the Polygonzkevm contract. +type PolygonzkevmSetPendingStateTimeoutIterator struct { + Event *PolygonzkevmSetPendingStateTimeout // 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 *PolygonzkevmSetPendingStateTimeoutIterator) 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(PolygonzkevmSetPendingStateTimeout) + 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(PolygonzkevmSetPendingStateTimeout) + 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 *PolygonzkevmSetPendingStateTimeoutIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetPendingStateTimeoutIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetPendingStateTimeout represents a SetPendingStateTimeout event raised by the Polygonzkevm contract. +type PolygonzkevmSetPendingStateTimeout struct { + NewPendingStateTimeout uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetPendingStateTimeout is a free log retrieval operation binding the contract event 0xc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75. +// +// Solidity: event SetPendingStateTimeout(uint64 newPendingStateTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetPendingStateTimeout(opts *bind.FilterOpts) (*PolygonzkevmSetPendingStateTimeoutIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetPendingStateTimeout") + if err != nil { + return nil, err + } + return &PolygonzkevmSetPendingStateTimeoutIterator{contract: _Polygonzkevm.contract, event: "SetPendingStateTimeout", logs: logs, sub: sub}, nil +} + +// WatchSetPendingStateTimeout is a free log subscription operation binding the contract event 0xc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75. +// +// Solidity: event SetPendingStateTimeout(uint64 newPendingStateTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetPendingStateTimeout(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetPendingStateTimeout) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetPendingStateTimeout") + 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(PolygonzkevmSetPendingStateTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetPendingStateTimeout", 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 +} + +// ParseSetPendingStateTimeout is a log parse operation binding the contract event 0xc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75. +// +// Solidity: event SetPendingStateTimeout(uint64 newPendingStateTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetPendingStateTimeout(log types.Log) (*PolygonzkevmSetPendingStateTimeout, error) { + event := new(PolygonzkevmSetPendingStateTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetPendingStateTimeout", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetTrustedAggregatorIterator is returned from FilterSetTrustedAggregator and is used to iterate over the raw logs and unpacked data for SetTrustedAggregator events raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedAggregatorIterator struct { + Event *PolygonzkevmSetTrustedAggregator // 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 *PolygonzkevmSetTrustedAggregatorIterator) 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(PolygonzkevmSetTrustedAggregator) + 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(PolygonzkevmSetTrustedAggregator) + 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 *PolygonzkevmSetTrustedAggregatorIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetTrustedAggregatorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetTrustedAggregator represents a SetTrustedAggregator event raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedAggregator struct { + NewTrustedAggregator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetTrustedAggregator is a free log retrieval operation binding the contract event 0x61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca. +// +// Solidity: event SetTrustedAggregator(address newTrustedAggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetTrustedAggregator(opts *bind.FilterOpts) (*PolygonzkevmSetTrustedAggregatorIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetTrustedAggregator") + if err != nil { + return nil, err + } + return &PolygonzkevmSetTrustedAggregatorIterator{contract: _Polygonzkevm.contract, event: "SetTrustedAggregator", logs: logs, sub: sub}, nil +} + +// WatchSetTrustedAggregator is a free log subscription operation binding the contract event 0x61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca. +// +// Solidity: event SetTrustedAggregator(address newTrustedAggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetTrustedAggregator(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetTrustedAggregator) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetTrustedAggregator") + 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(PolygonzkevmSetTrustedAggregator) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedAggregator", 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 +} + +// ParseSetTrustedAggregator is a log parse operation binding the contract event 0x61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca. +// +// Solidity: event SetTrustedAggregator(address newTrustedAggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetTrustedAggregator(log types.Log) (*PolygonzkevmSetTrustedAggregator, error) { + event := new(PolygonzkevmSetTrustedAggregator) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedAggregator", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetTrustedAggregatorTimeoutIterator is returned from FilterSetTrustedAggregatorTimeout and is used to iterate over the raw logs and unpacked data for SetTrustedAggregatorTimeout events raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedAggregatorTimeoutIterator struct { + Event *PolygonzkevmSetTrustedAggregatorTimeout // 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 *PolygonzkevmSetTrustedAggregatorTimeoutIterator) 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(PolygonzkevmSetTrustedAggregatorTimeout) + 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(PolygonzkevmSetTrustedAggregatorTimeout) + 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 *PolygonzkevmSetTrustedAggregatorTimeoutIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetTrustedAggregatorTimeoutIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetTrustedAggregatorTimeout represents a SetTrustedAggregatorTimeout event raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedAggregatorTimeout struct { + NewTrustedAggregatorTimeout uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetTrustedAggregatorTimeout is a free log retrieval operation binding the contract event 0x1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1. +// +// Solidity: event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetTrustedAggregatorTimeout(opts *bind.FilterOpts) (*PolygonzkevmSetTrustedAggregatorTimeoutIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetTrustedAggregatorTimeout") + if err != nil { + return nil, err + } + return &PolygonzkevmSetTrustedAggregatorTimeoutIterator{contract: _Polygonzkevm.contract, event: "SetTrustedAggregatorTimeout", logs: logs, sub: sub}, nil +} + +// WatchSetTrustedAggregatorTimeout is a free log subscription operation binding the contract event 0x1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1. +// +// Solidity: event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetTrustedAggregatorTimeout(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetTrustedAggregatorTimeout) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetTrustedAggregatorTimeout") + 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(PolygonzkevmSetTrustedAggregatorTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedAggregatorTimeout", 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 +} + +// ParseSetTrustedAggregatorTimeout is a log parse operation binding the contract event 0x1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1. +// +// Solidity: event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetTrustedAggregatorTimeout(log types.Log) (*PolygonzkevmSetTrustedAggregatorTimeout, error) { + event := new(PolygonzkevmSetTrustedAggregatorTimeout) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedAggregatorTimeout", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetTrustedSequencerIterator is returned from FilterSetTrustedSequencer and is used to iterate over the raw logs and unpacked data for SetTrustedSequencer events raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedSequencerIterator struct { + Event *PolygonzkevmSetTrustedSequencer // 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 *PolygonzkevmSetTrustedSequencerIterator) 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(PolygonzkevmSetTrustedSequencer) + 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(PolygonzkevmSetTrustedSequencer) + 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 *PolygonzkevmSetTrustedSequencerIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetTrustedSequencerIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetTrustedSequencer represents a SetTrustedSequencer event raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedSequencer struct { + NewTrustedSequencer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetTrustedSequencer is a free log retrieval operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. +// +// Solidity: event SetTrustedSequencer(address newTrustedSequencer) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetTrustedSequencer(opts *bind.FilterOpts) (*PolygonzkevmSetTrustedSequencerIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetTrustedSequencer") + if err != nil { + return nil, err + } + return &PolygonzkevmSetTrustedSequencerIterator{contract: _Polygonzkevm.contract, event: "SetTrustedSequencer", logs: logs, sub: sub}, nil +} + +// WatchSetTrustedSequencer is a free log subscription operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. +// +// Solidity: event SetTrustedSequencer(address newTrustedSequencer) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetTrustedSequencer(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetTrustedSequencer) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetTrustedSequencer") + 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(PolygonzkevmSetTrustedSequencer) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedSequencer", 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 +} + +// ParseSetTrustedSequencer is a log parse operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. +// +// Solidity: event SetTrustedSequencer(address newTrustedSequencer) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetTrustedSequencer(log types.Log) (*PolygonzkevmSetTrustedSequencer, error) { + event := new(PolygonzkevmSetTrustedSequencer) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedSequencer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetTrustedSequencerURLIterator is returned from FilterSetTrustedSequencerURL and is used to iterate over the raw logs and unpacked data for SetTrustedSequencerURL events raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedSequencerURLIterator struct { + Event *PolygonzkevmSetTrustedSequencerURL // 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 *PolygonzkevmSetTrustedSequencerURLIterator) 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(PolygonzkevmSetTrustedSequencerURL) + 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(PolygonzkevmSetTrustedSequencerURL) + 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 *PolygonzkevmSetTrustedSequencerURLIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetTrustedSequencerURLIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetTrustedSequencerURL represents a SetTrustedSequencerURL event raised by the Polygonzkevm contract. +type PolygonzkevmSetTrustedSequencerURL struct { + NewTrustedSequencerURL string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetTrustedSequencerURL is a free log retrieval operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. +// +// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetTrustedSequencerURL(opts *bind.FilterOpts) (*PolygonzkevmSetTrustedSequencerURLIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetTrustedSequencerURL") + if err != nil { + return nil, err + } + return &PolygonzkevmSetTrustedSequencerURLIterator{contract: _Polygonzkevm.contract, event: "SetTrustedSequencerURL", logs: logs, sub: sub}, nil +} + +// WatchSetTrustedSequencerURL is a free log subscription operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. +// +// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetTrustedSequencerURL(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetTrustedSequencerURL) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetTrustedSequencerURL") + 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(PolygonzkevmSetTrustedSequencerURL) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedSequencerURL", 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 +} + +// ParseSetTrustedSequencerURL is a log parse operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. +// +// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetTrustedSequencerURL(log types.Log) (*PolygonzkevmSetTrustedSequencerURL, error) { + event := new(PolygonzkevmSetTrustedSequencerURL) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetTrustedSequencerURL", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmSetVerifyBatchTimeTargetIterator is returned from FilterSetVerifyBatchTimeTarget and is used to iterate over the raw logs and unpacked data for SetVerifyBatchTimeTarget events raised by the Polygonzkevm contract. +type PolygonzkevmSetVerifyBatchTimeTargetIterator struct { + Event *PolygonzkevmSetVerifyBatchTimeTarget // 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 *PolygonzkevmSetVerifyBatchTimeTargetIterator) 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(PolygonzkevmSetVerifyBatchTimeTarget) + 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(PolygonzkevmSetVerifyBatchTimeTarget) + 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 *PolygonzkevmSetVerifyBatchTimeTargetIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmSetVerifyBatchTimeTargetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmSetVerifyBatchTimeTarget represents a SetVerifyBatchTimeTarget event raised by the Polygonzkevm contract. +type PolygonzkevmSetVerifyBatchTimeTarget struct { + NewVerifyBatchTimeTarget uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSetVerifyBatchTimeTarget is a free log retrieval operation binding the contract event 0x1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28. +// +// Solidity: event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterSetVerifyBatchTimeTarget(opts *bind.FilterOpts) (*PolygonzkevmSetVerifyBatchTimeTargetIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "SetVerifyBatchTimeTarget") + if err != nil { + return nil, err + } + return &PolygonzkevmSetVerifyBatchTimeTargetIterator{contract: _Polygonzkevm.contract, event: "SetVerifyBatchTimeTarget", logs: logs, sub: sub}, nil +} + +// WatchSetVerifyBatchTimeTarget is a free log subscription operation binding the contract event 0x1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28. +// +// Solidity: event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchSetVerifyBatchTimeTarget(opts *bind.WatchOpts, sink chan<- *PolygonzkevmSetVerifyBatchTimeTarget) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "SetVerifyBatchTimeTarget") + 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(PolygonzkevmSetVerifyBatchTimeTarget) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetVerifyBatchTimeTarget", 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 +} + +// ParseSetVerifyBatchTimeTarget is a log parse operation binding the contract event 0x1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28. +// +// Solidity: event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseSetVerifyBatchTimeTarget(log types.Log) (*PolygonzkevmSetVerifyBatchTimeTarget, error) { + event := new(PolygonzkevmSetVerifyBatchTimeTarget) + if err := _Polygonzkevm.contract.UnpackLog(event, "SetVerifyBatchTimeTarget", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmTransferAdminRoleIterator is returned from FilterTransferAdminRole and is used to iterate over the raw logs and unpacked data for TransferAdminRole events raised by the Polygonzkevm contract. +type PolygonzkevmTransferAdminRoleIterator struct { + Event *PolygonzkevmTransferAdminRole // 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 *PolygonzkevmTransferAdminRoleIterator) 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(PolygonzkevmTransferAdminRole) + 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(PolygonzkevmTransferAdminRole) + 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 *PolygonzkevmTransferAdminRoleIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmTransferAdminRoleIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmTransferAdminRole represents a TransferAdminRole event raised by the Polygonzkevm contract. +type PolygonzkevmTransferAdminRole struct { + NewPendingAdmin common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransferAdminRole is a free log retrieval operation binding the contract event 0xa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6. +// +// Solidity: event TransferAdminRole(address newPendingAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterTransferAdminRole(opts *bind.FilterOpts) (*PolygonzkevmTransferAdminRoleIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "TransferAdminRole") + if err != nil { + return nil, err + } + return &PolygonzkevmTransferAdminRoleIterator{contract: _Polygonzkevm.contract, event: "TransferAdminRole", logs: logs, sub: sub}, nil +} + +// WatchTransferAdminRole is a free log subscription operation binding the contract event 0xa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6. +// +// Solidity: event TransferAdminRole(address newPendingAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchTransferAdminRole(opts *bind.WatchOpts, sink chan<- *PolygonzkevmTransferAdminRole) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "TransferAdminRole") + 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(PolygonzkevmTransferAdminRole) + if err := _Polygonzkevm.contract.UnpackLog(event, "TransferAdminRole", 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 +} + +// ParseTransferAdminRole is a log parse operation binding the contract event 0xa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6. +// +// Solidity: event TransferAdminRole(address newPendingAdmin) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseTransferAdminRole(log types.Log) (*PolygonzkevmTransferAdminRole, error) { + event := new(PolygonzkevmTransferAdminRole) + if err := _Polygonzkevm.contract.UnpackLog(event, "TransferAdminRole", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmUpdateZkEVMVersionIterator is returned from FilterUpdateZkEVMVersion and is used to iterate over the raw logs and unpacked data for UpdateZkEVMVersion events raised by the Polygonzkevm contract. +type PolygonzkevmUpdateZkEVMVersionIterator struct { + Event *PolygonzkevmUpdateZkEVMVersion // 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 *PolygonzkevmUpdateZkEVMVersionIterator) 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(PolygonzkevmUpdateZkEVMVersion) + 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(PolygonzkevmUpdateZkEVMVersion) + 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 *PolygonzkevmUpdateZkEVMVersionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmUpdateZkEVMVersionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmUpdateZkEVMVersion represents a UpdateZkEVMVersion event raised by the Polygonzkevm contract. +type PolygonzkevmUpdateZkEVMVersion struct { + NumBatch uint64 + ForkID uint64 + Version string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateZkEVMVersion is a free log retrieval operation binding the contract event 0xed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd6. +// +// Solidity: event UpdateZkEVMVersion(uint64 numBatch, uint64 forkID, string version) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterUpdateZkEVMVersion(opts *bind.FilterOpts) (*PolygonzkevmUpdateZkEVMVersionIterator, error) { + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "UpdateZkEVMVersion") + if err != nil { + return nil, err + } + return &PolygonzkevmUpdateZkEVMVersionIterator{contract: _Polygonzkevm.contract, event: "UpdateZkEVMVersion", logs: logs, sub: sub}, nil +} + +// WatchUpdateZkEVMVersion is a free log subscription operation binding the contract event 0xed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd6. +// +// Solidity: event UpdateZkEVMVersion(uint64 numBatch, uint64 forkID, string version) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchUpdateZkEVMVersion(opts *bind.WatchOpts, sink chan<- *PolygonzkevmUpdateZkEVMVersion) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "UpdateZkEVMVersion") + 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(PolygonzkevmUpdateZkEVMVersion) + if err := _Polygonzkevm.contract.UnpackLog(event, "UpdateZkEVMVersion", 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 +} + +// ParseUpdateZkEVMVersion is a log parse operation binding the contract event 0xed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd6. +// +// Solidity: event UpdateZkEVMVersion(uint64 numBatch, uint64 forkID, string version) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseUpdateZkEVMVersion(log types.Log) (*PolygonzkevmUpdateZkEVMVersion, error) { + event := new(PolygonzkevmUpdateZkEVMVersion) + if err := _Polygonzkevm.contract.UnpackLog(event, "UpdateZkEVMVersion", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmVerifyBatchesIterator is returned from FilterVerifyBatches and is used to iterate over the raw logs and unpacked data for VerifyBatches events raised by the Polygonzkevm contract. +type PolygonzkevmVerifyBatchesIterator struct { + Event *PolygonzkevmVerifyBatches // 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 *PolygonzkevmVerifyBatchesIterator) 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(PolygonzkevmVerifyBatches) + 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(PolygonzkevmVerifyBatches) + 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 *PolygonzkevmVerifyBatchesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmVerifyBatchesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmVerifyBatches represents a VerifyBatches event raised by the Polygonzkevm contract. +type PolygonzkevmVerifyBatches struct { + NumBatch uint64 + StateRoot [32]byte + Aggregator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterVerifyBatches is a free log retrieval operation binding the contract event 0x9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966. +// +// Solidity: event VerifyBatches(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterVerifyBatches(opts *bind.FilterOpts, numBatch []uint64, aggregator []common.Address) (*PolygonzkevmVerifyBatchesIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "VerifyBatches", numBatchRule, aggregatorRule) + if err != nil { + return nil, err + } + return &PolygonzkevmVerifyBatchesIterator{contract: _Polygonzkevm.contract, event: "VerifyBatches", logs: logs, sub: sub}, nil +} + +// WatchVerifyBatches is a free log subscription operation binding the contract event 0x9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966. +// +// Solidity: event VerifyBatches(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchVerifyBatches(opts *bind.WatchOpts, sink chan<- *PolygonzkevmVerifyBatches, numBatch []uint64, aggregator []common.Address) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "VerifyBatches", numBatchRule, aggregatorRule) + 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(PolygonzkevmVerifyBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "VerifyBatches", 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 +} + +// ParseVerifyBatches is a log parse operation binding the contract event 0x9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f5966. +// +// Solidity: event VerifyBatches(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseVerifyBatches(log types.Log) (*PolygonzkevmVerifyBatches, error) { + event := new(PolygonzkevmVerifyBatches) + if err := _Polygonzkevm.contract.UnpackLog(event, "VerifyBatches", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmVerifyBatchesTrustedAggregatorIterator is returned from FilterVerifyBatchesTrustedAggregator and is used to iterate over the raw logs and unpacked data for VerifyBatchesTrustedAggregator events raised by the Polygonzkevm contract. +type PolygonzkevmVerifyBatchesTrustedAggregatorIterator struct { + Event *PolygonzkevmVerifyBatchesTrustedAggregator // 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 *PolygonzkevmVerifyBatchesTrustedAggregatorIterator) 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(PolygonzkevmVerifyBatchesTrustedAggregator) + 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(PolygonzkevmVerifyBatchesTrustedAggregator) + 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 *PolygonzkevmVerifyBatchesTrustedAggregatorIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmVerifyBatchesTrustedAggregatorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmVerifyBatchesTrustedAggregator represents a VerifyBatchesTrustedAggregator event raised by the Polygonzkevm contract. +type PolygonzkevmVerifyBatchesTrustedAggregator struct { + NumBatch uint64 + StateRoot [32]byte + Aggregator common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterVerifyBatchesTrustedAggregator is a free log retrieval operation binding the contract event 0xcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe. +// +// Solidity: event VerifyBatchesTrustedAggregator(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) FilterVerifyBatchesTrustedAggregator(opts *bind.FilterOpts, numBatch []uint64, aggregator []common.Address) (*PolygonzkevmVerifyBatchesTrustedAggregatorIterator, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.FilterLogs(opts, "VerifyBatchesTrustedAggregator", numBatchRule, aggregatorRule) + if err != nil { + return nil, err + } + return &PolygonzkevmVerifyBatchesTrustedAggregatorIterator{contract: _Polygonzkevm.contract, event: "VerifyBatchesTrustedAggregator", logs: logs, sub: sub}, nil +} + +// WatchVerifyBatchesTrustedAggregator is a free log subscription operation binding the contract event 0xcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe. +// +// Solidity: event VerifyBatchesTrustedAggregator(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) WatchVerifyBatchesTrustedAggregator(opts *bind.WatchOpts, sink chan<- *PolygonzkevmVerifyBatchesTrustedAggregator, numBatch []uint64, aggregator []common.Address) (event.Subscription, error) { + + var numBatchRule []interface{} + for _, numBatchItem := range numBatch { + numBatchRule = append(numBatchRule, numBatchItem) + } + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _Polygonzkevm.contract.WatchLogs(opts, "VerifyBatchesTrustedAggregator", numBatchRule, aggregatorRule) + 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(PolygonzkevmVerifyBatchesTrustedAggregator) + if err := _Polygonzkevm.contract.UnpackLog(event, "VerifyBatchesTrustedAggregator", 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 +} + +// ParseVerifyBatchesTrustedAggregator is a log parse operation binding the contract event 0xcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe. +// +// Solidity: event VerifyBatchesTrustedAggregator(uint64 indexed numBatch, bytes32 stateRoot, address indexed aggregator) +func (_Polygonzkevm *PolygonzkevmFilterer) ParseVerifyBatchesTrustedAggregator(log types.Log) (*PolygonzkevmVerifyBatchesTrustedAggregator, error) { + event := new(PolygonzkevmVerifyBatchesTrustedAggregator) + if err := _Polygonzkevm.contract.UnpackLog(event, "VerifyBatchesTrustedAggregator", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/etherman/smartcontracts/polygonzkevmbridge/polygonzkevmbridge.go b/etherman/smartcontracts/polygonzkevmbridge/polygonzkevmbridge.go new file mode 100644 index 0000000000..5192788052 --- /dev/null +++ b/etherman/smartcontracts/polygonzkevmbridge/polygonzkevmbridge.go @@ -0,0 +1,1666 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package polygonzkevmbridge + +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 + _ = abi.ConvertType +) + +// PolygonzkevmbridgeMetaData contains all meta data concerning the Polygonzkevmbridge contract. +var PolygonzkevmbridgeMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"AlreadyClaimed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AmountDoesNotMatchMsgValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DestinationNetworkInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EtherTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GlobalExitRootInvalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSmtProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MerkleTreeFull\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueNotZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotValidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotValidOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotValidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyEmergencyState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyNotEmergencyState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPolygonZkEVM\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"leafType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"depositCount\",\"type\":\"uint32\"}],\"name\":\"BridgeEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ClaimEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EmergencyStateActivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EmergencyStateDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"wrappedTokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"NewWrappedToken\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"activateEmergencyState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"forceUpdateGlobalExitRoot\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"permitData\",\"type\":\"bytes\"}],\"name\":\"bridgeAsset\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"forceUpdateGlobalExitRoot\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"bridgeMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[32]\",\"name\":\"smtProof\",\"type\":\"bytes32[32]\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"mainnetExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"rollupExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"claimAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[32]\",\"name\":\"smtProof\",\"type\":\"bytes32[32]\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"mainnetExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"rollupExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"name\":\"claimMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimedBitMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deactivateEmergencyState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDepositRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"leafType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destinationNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"destinationAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"name\":\"getLeafValue\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"}],\"name\":\"getTokenWrappedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalExitRootManager\",\"outputs\":[{\"internalType\":\"contractIBasePolygonZkEVMGlobalExitRoot\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_networkID\",\"type\":\"uint32\"},{\"internalType\":\"contractIBasePolygonZkEVMGlobalExitRoot\",\"name\":\"_globalExitRootManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_polygonZkEVMaddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"isClaimed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isEmergencyState\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastUpdatedDepositCount\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"networkID\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"polygonZkEVMaddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"name\":\"precalculatedWrapperAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"tokenInfoToWrappedToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"updateGlobalExitRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[32]\",\"name\":\"smtProof\",\"type\":\"bytes32[32]\"},{\"internalType\":\"uint32\",\"name\":\"index\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"verifyMerkleProof\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"wrappedTokenToTokenInfo\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"originNetwork\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"originTokenAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50614e0e806100206000396000f3fe6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000506578063ee25560b146200051e578063fb570834146200054f57600080fd5b8063be5831c7146200049e578063cd58657914620004c4578063d02103ca14620004db57600080fd5b80639e34070f11620000be5780639e34070f14620003fa578063aaa13cc2146200043f578063bab161bf146200046457600080fd5b8063647c576c146200038357806379e2cf9714620003a857806381b1c17414620003c057600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf214620003245780633ae0504714620003465780633e197043146200035e57600080fd5b80632d2c9d9414620002695780632dfdf0b5146200028e578063318aee3d14620002b557600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200022d5780632cffd02e146200024457600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed62000574565b005b348015620001fc57600080fd5b50620002146200020e36600462002938565b620005ac565b6040516001600160a01b039091168152602001620001cc565b620001ed6200023e366004620029cf565b62000617565b3480156200025157600080fd5b50620001ed6200026336600462002a66565b6200073e565b3480156200027657600080fd5b50620001ed6200028836600462002a66565b62000b98565b3480156200029b57600080fd5b50620002a660535481565b604051908152602001620001cc565b348015620002c257600080fd5b50620002ff620002d436600462002b4c565b606b6020526000908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201620001cc565b3480156200033157600080fd5b50606c5462000214906001600160a01b031681565b3480156200035357600080fd5b50620002a662000d36565b3480156200036b57600080fd5b50620002a66200037d36600462002b7c565b62000e1c565b3480156200039057600080fd5b50620001ed620003a236600462002c06565b62000ec6565b348015620003b557600080fd5b50620001ed62001096565b348015620003cd57600080fd5b5062000214620003df36600462002c56565b606a602052600090815260409020546001600160a01b031681565b3480156200040757600080fd5b50620001c06200041936600462002c56565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200044c57600080fd5b50620002146200045e36600462002c70565b620010ba565b3480156200047157600080fd5b506068546200048890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620004ab57600080fd5b506068546200048890600160c81b900463ffffffff1681565b620001ed620004d536600462002d24565b6200120e565b348015620004e857600080fd5b5060685462000214906501000000000090046001600160a01b031681565b3480156200051357600080fd5b50620001ed620015f1565b3480156200052b57600080fd5b50620002a66200053d36600462002c56565b60696020526000908152604090205481565b3480156200055c57600080fd5b50620001c06200056e36600462002dc6565b62001627565b606c546001600160a01b03163314620005a05760405163e2e8106b60e01b815260040160405180910390fd5b620005aa6200170e565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091206000908152606a90915220546001600160a01b03165b92915050565b60685460ff16156200063c57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff868116610100909204161480620006625750600263ffffffff861610155b1562000681576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620006d79998979695949392919062002e3c565b60405180910390a162000726620007206001606860019054906101000a900463ffffffff163389893489896040516200071292919062002eaa565b604051809103902062000e1c565b6200176b565b821562000737576200073762001882565b5050505050565b60685460ff16156200076357604051630bc011ff60e21b815260040160405180910390fd5b6200077a8b8b8b8b8b8b8b8b8b8b8b600062001934565b6001600160a01b0386166200083c57604080516000808252602082019092526001600160a01b038616908590604051620007b5919062002ef6565b60006040518083038185875af1925050503d8060008114620007f4576040519150601f19603f3d011682016040523d82523d6000602084013e620007f9565b606091505b505090508062000835576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000b2d565b60685463ffffffff61010090910481169088160362000871576200086b6001600160a01b038716858562001aff565b62000b2d565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152606a9093529120549091506001600160a01b03168062000ac55760008080620008f08688018862002fcf565b9250925092506000858484846040516200090a90620028fc565b620009189392919062003073565b8190604051809103906000f590508015801562000939573d6000803e3d6000fd5b506040516340c10f1960e01b81526001600160a01b038c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b1580156200098957600080fd5b505af11580156200099e573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808e63ffffffff1681526020018d6001600160a01b0316815250606b6000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000ab3959493929190620030b0565b60405180910390a15050505062000b2a565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000b1057600080fd5b505af115801562000b25573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c81168252891660208201526001600160a01b0388811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000bbd57604051630bc011ff60e21b815260040160405180910390fd5b62000bd48b8b8b8b8b8b8b8b8b8b8b600162001934565b6000846001600160a01b031684888a868660405160240162000bfa9493929190620030eb565b60408051601f198184030181529181526020820180516001600160e01b03167f1806b5f2000000000000000000000000000000000000000000000000000000001790525162000c4a919062002ef6565b60006040518083038185875af1925050503d806000811462000c89576040519150601f19603f3d011682016040523d82523d6000602084013e62000c8e565b606091505b505090508062000cca576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562000e13578083901c60011660010362000da4576033816020811062000d705762000d7062003126565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062000dd1565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b6040805160208101849052908101839052606001604051602081830303815290604052805190602001209150808062000e0a9062003152565b91505062000d41565b50919392505050565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b600054610100900460ff161580801562000ee75750600054600160ff909116105b8062000f035750303b15801562000f03575060005460ff166001145b62000f7b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff19166001179055801562000f9f576000805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556200104962001b7d565b801562001090576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854600160c81b900463ffffffff161015620005aa57620005aa62001882565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200112590620028fc565b601f1982820381018352601f90910116604081905262001152908d908d908d908d908d906020016200316e565b60408051601f1981840301815290829052620011729291602001620031af565b60405160208183030381529060405280519060200120604051602001620011e894939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f1901815291905280516020909101209a9950505050505050505050565b60685460ff16156200123357604051630bc011ff60e21b815260040160405180910390fd5b6200123d62001bf4565b60685463ffffffff888116610100909204161480620012635750600263ffffffff881610155b1562001282576040516302caf51760e11b815260040160405180910390fd5b6000806060876001600160a01b038816620012db57883414620012d1576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001562565b341562001314576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038089166000908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620013ea576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b90526001600160a01b038a1690639dc29fac90604401600060405180830381600087803b158015620013bd57600080fd5b505af1158015620013d2573d6000803e3d6000fd5b50505050806020015194508060000151935062001560565b8515620013ff57620013ff898b898962001c4f565b6040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa15801562001447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200146d9190620031e2565b9050620014866001600160a01b038b1633308e62002015565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa158015620014ce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620014f49190620031e2565b9050620015028282620031fc565b6068548c9850610100900463ffffffff1696509350620015228762002068565b6200152d8c62002166565b620015388d62002251565b6040516020016200154c9392919062003073565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e8688605354604051620015a498979695949392919062003212565b60405180910390a1620015c962000720600085878f8f87898051906020012062000e1c565b8615620015da57620015da62001882565b50505050620015e860018055565b50505050505050565b606c546001600160a01b031633146200161d5760405163e2e8106b60e01b815260040160405180910390fd5b620005aa62002331565b600084815b60208110156200170257600163ffffffff8616821c811690036200169e578581602081106200165f576200165f62003126565b60200201358260405160200162001680929190918252602082015260400190565b604051602081830303815290604052805190602001209150620016ed565b81868260208110620016b457620016b462003126565b6020020135604051602001620016d4929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80620016f98162003152565b9150506200162c565b50909114949350505050565b60685460ff16156200173357604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b8060016200177c602060026200337b565b620017889190620031fc565b60535410620017c3576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000605360008154620017d69062003152565b9182905550905060005b602081101562001872578082901c6001166001036200181857826033826020811062001810576200181062003126565b015550505050565b603381602081106200182e576200182e62003126565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080620018699062003152565b915050620017e0565b506200187d62003389565b505050565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d620018e562000d36565b6040518263ffffffff1660e01b81526004016200190491815260200190565b600060405180830381600087803b1580156200191f57600080fd5b505af115801562001090573d6000803e3d6000fd5b620019458b63ffffffff16620023a3565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091526000916501000000000090046001600160a01b03169063257b3632906084016020604051808303816000875af1158015620019db573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a019190620031e2565b90508060000362001a3d576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001a6e576040516302caf51760e11b815260040160405180910390fd5b606854600090610100900463ffffffff1662001a8c57508962001a8f565b508a5b62001ab862001aaf848c8c8c8c8c8c8c6040516200071292919062002eaa565b8f8f8462001627565b62001aef576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b6040516001600160a01b0383166024820152604481018290526200187d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262002408565b600054610100900460ff1662001bea5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000f72565b620005aa620024f4565b60026001540362001c485760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162000f72565b6002600155565b600062001c6060048284866200339f565b62001c6b91620033cb565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b031982160162001e5757600080808080808062001cb6896004818d6200339f565b81019062001cc59190620033fc565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161462001d065760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301462001d305760405163750643af60e01b815260040160405180910390fd5b8a851462001d6a576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162001e03919062002ef6565b6000604051808303816000865af19150503d806000811462001e42576040519150601f19603f3d011682016040523d82523d6000602084013e62001e47565b606091505b5050505050505050505062000737565b6001600160e01b031981166323f2ebc360e21b1462001ea2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808080808062001eba8a6004818e6200339f565b81019062001ec9919062003457565b97509750975097509750975097509750336001600160a01b0316886001600160a01b03161462001f0c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301462001f365760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169162001fbf919062002ef6565b6000604051808303816000865af19150503d806000811462001ffe576040519150601f19603f3d011682016040523d82523d6000602084013e62002003565b606091505b50505050505050505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620010909085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162001b45565b60408051600481526024810182526020810180516001600160e01b03167f06fdde0300000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b03861691620020ca919062002ef6565b600060405180830381855afa9150503d806000811462002107576040519150601f19603f3d011682016040523d82523d6000602084013e6200210c565b606091505b50915091508162002153576040518060400160405280600781526020017f4e4f5f4e414d45000000000000000000000000000000000000000000000000008152506200215e565b6200215e8162002561565b949350505050565b60408051600481526024810182526020810180516001600160e01b03167f95d89b4100000000000000000000000000000000000000000000000000000000179052905160609160009182916001600160a01b03861691620021c8919062002ef6565b600060405180830381855afa9150503d806000811462002205576040519150601f19603f3d011682016040523d82523d6000602084013e6200220a565b606091505b50915091508162002153576040518060400160405280600981526020017f4e4f5f53594d424f4c00000000000000000000000000000000000000000000008152506200215e565b60408051600481526024810182526020810180516001600160e01b03167f313ce567000000000000000000000000000000000000000000000000000000001790529051600091829182916001600160a01b03861691620022b2919062002ef6565b600060405180830381855afa9150503d8060008114620022ef576040519150601f19603f3d011682016040523d82523d6000602084013e620022f4565b606091505b509150915081801562002308575080516020145b620023155760126200215e565b808060200190518101906200215e9190620034e3565b60018055565b60685460ff166200236e576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000737576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006200245f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620027519092919063ffffffff16565b8051909150156200187d578080602001905181019062002480919062003503565b6200187d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000f72565b600054610100900460ff166200232b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000f72565b6060604082511062002583578180602001905181019062000611919062003523565b8151602003620027135760005b602081108015620025db5750828181518110620025b157620025b162003126565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620025f65780620025ed8162003152565b91505062002590565b806000036200263a57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562002658576200265862002eba565b6040519080825280601f01601f19166020018201604052801562002683576020820181803683370190505b50905060005b828110156200270b57848181518110620026a757620026a762003126565b602001015160f81c60f81b828281518110620026c757620026c762003126565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620027028162003152565b91505062002689565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60606200276284846000856200276c565b90505b9392505050565b606082471015620027e65760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000f72565b6001600160a01b0385163b6200283f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000f72565b600080866001600160a01b031685876040516200285d919062002ef6565b60006040518083038185875af1925050503d80600081146200289c576040519150601f19603f3d011682016040523d82523d6000602084013e620028a1565b606091505b5091509150620028b3828286620028be565b979650505050505050565b60608315620028cf57508162002765565b825115620028e05782518084602001fd5b8160405162461bcd60e51b815260040162000f729190620035a3565b61182080620035b983390190565b803563ffffffff811681146200274c57600080fd5b6001600160a01b03811681146200293557600080fd5b50565b600080604083850312156200294c57600080fd5b62002957836200290a565b9150602083013562002969816200291f565b809150509250929050565b80151581146200293557600080fd5b60008083601f8401126200299657600080fd5b50813567ffffffffffffffff811115620029af57600080fd5b602083019150836020828501011115620029c857600080fd5b9250929050565b600080600080600060808688031215620029e857600080fd5b620029f3866200290a565b9450602086013562002a05816200291f565b9350604086013562002a178162002974565b9250606086013567ffffffffffffffff81111562002a3457600080fd5b62002a428882890162002983565b969995985093965092949392505050565b8061040081018310156200061157600080fd5b60008060008060008060008060008060006105208c8e03121562002a8957600080fd5b62002a958d8d62002a53565b9a5062002aa66104008d016200290a565b99506104208c013598506104408c0135975062002ac76104608d016200290a565b96506104808c013562002ada816200291f565b955062002aeb6104a08d016200290a565b94506104c08c013562002afe816200291f565b93506104e08c013592506105008c013567ffffffffffffffff81111562002b2457600080fd5b62002b328e828f0162002983565b915080935050809150509295989b509295989b9093969950565b60006020828403121562002b5f57600080fd5b813562002765816200291f565b60ff811681146200293557600080fd5b600080600080600080600060e0888a03121562002b9857600080fd5b873562002ba58162002b6c565b965062002bb5602089016200290a565b9550604088013562002bc7816200291f565b945062002bd7606089016200290a565b9350608088013562002be9816200291f565b9699959850939692959460a0840135945060c09093013592915050565b60008060006060848603121562002c1c57600080fd5b62002c27846200290a565b9250602084013562002c39816200291f565b9150604084013562002c4b816200291f565b809150509250925092565b60006020828403121562002c6957600080fd5b5035919050565b600080600080600080600060a0888a03121562002c8c57600080fd5b62002c97886200290a565b9650602088013562002ca9816200291f565b9550604088013567ffffffffffffffff8082111562002cc757600080fd5b62002cd58b838c0162002983565b909750955060608a013591508082111562002cef57600080fd5b5062002cfe8a828b0162002983565b909450925050608088013562002d148162002b6c565b8091505092959891949750929550565b600080600080600080600060c0888a03121562002d4057600080fd5b62002d4b886200290a565b9650602088013562002d5d816200291f565b955060408801359450606088013562002d76816200291f565b9350608088013562002d888162002974565b925060a088013567ffffffffffffffff81111562002da557600080fd5b62002db38a828b0162002983565b989b979a50959850939692959293505050565b600080600080610460858703121562002dde57600080fd5b8435935062002df1866020870162002a53565b925062002e0261042086016200290a565b939692955092936104400135925050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600061010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015262002e90828501878962002e13565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562002eed57818101518382015260200162002ed3565b50506000910152565b6000825162002f0a81846020870162002ed0565b9190910192915050565b604051601f8201601f1916810167ffffffffffffffff8111828210171562002f405762002f4062002eba565b604052919050565b600067ffffffffffffffff82111562002f655762002f6562002eba565b50601f01601f191660200190565b600082601f83011262002f8557600080fd5b813562002f9c62002f968262002f48565b62002f14565b81815284602083860101111562002fb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562002fe557600080fd5b833567ffffffffffffffff8082111562002ffe57600080fd5b6200300c8783880162002f73565b945060208601359150808211156200302357600080fd5b50620030328682870162002f73565b925050604084013562002c4b8162002b6c565b600081518084526200305f81602086016020860162002ed0565b601f01601f19169290920160200192915050565b60608152600062003088606083018662003045565b82810360208401526200309c818662003045565b91505060ff83166040830152949350505050565b63ffffffff8616815260006001600160a01b03808716602084015280861660408401525060806060830152620028b360808301848662002e13565b6001600160a01b038516815263ffffffff841660208201526060604082015260006200311c60608301848662002e13565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016200316757620031676200313c565b5060010190565b6060815260006200318460608301878962002e13565b82810360208401526200319981868862002e13565b91505060ff831660408301529695505050505050565b60008351620031c381846020880162002ed0565b835190830190620031d981836020880162002ed0565b01949350505050565b600060208284031215620031f557600080fd5b5051919050565b818103818111156200061157620006116200313c565b600061010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620032658285018762003045565b925080851660e085015250509998505050505050505050565b600181815b80851115620032bf578160001904821115620032a357620032a36200313c565b80851615620032b157918102915b93841c939080029062003283565b509250929050565b600082620032d85750600162000611565b81620032e75750600062000611565b81600181146200330057600281146200330b576200332b565b600191505062000611565b60ff8411156200331f576200331f6200313c565b50506001821b62000611565b5060208310610133831016604e8410600b841016171562003350575081810a62000611565b6200335c83836200327e565b80600019048211156200337357620033736200313c565b029392505050565b6000620027658383620032c7565b634e487b7160e01b600052600160045260246000fd5b60008085851115620033b057600080fd5b83861115620033be57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015620033f45780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a0312156200341857600080fd5b873562003425816200291f565b9650602088013562003437816200291f565b95506040880135945060608801359350608088013562002be98162002b6c565b600080600080600080600080610100898b0312156200347557600080fd5b883562003482816200291f565b9750602089013562003494816200291f565b965060408901359550606089013594506080890135620034b48162002974565b935060a0890135620034c68162002b6c565b979a969950949793969295929450505060c08201359160e0013590565b600060208284031215620034f657600080fd5b8151620027658162002b6c565b6000602082840312156200351657600080fd5b8151620027658162002974565b6000602082840312156200353657600080fd5b815167ffffffffffffffff8111156200354e57600080fd5b8201601f810184136200356057600080fd5b80516200357162002f968262002f48565b8181528560208385010111156200358757600080fd5b6200359a82602083016020860162002ed0565b95945050505050565b6020815260006200276560208301846200304556fe6101006040523480156200001257600080fd5b50604051620018203803806200182083398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051611364620004bc60003960006102370152600081816102fa015281816105630152610623015260006104f701526000818161035f01526104c101526113646000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf14610381578063dd62ed3e14610394578063ffa1ad74146103cd57600080fd5b8063a457c2d714610334578063a9059cbb14610347578063cd0d00961461035a57600080fd5b806395d89b41116100bd57806395d89b41146102da5780639dc29fac146102e2578063a3c573eb146102f557600080fd5b806370a08231146102915780637ecebe00146102ba57600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103ed565b6040516101919190611107565b60405180910390f35b6101ad6101a8366004611171565b61047f565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad61020436600461119b565b610499565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c16104bd565b6101ad610277366004611171565b610519565b61028f61028a366004611171565b610558565b005b6101c161029f3660046111d7565b6001600160a01b031660009081526020819052604090205490565b6101c16102c83660046111d7565b60056020526000908152604090205481565b610184610609565b61028f6102f0366004611171565b610618565b61031c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610191565b6101ad610342366004611171565b6106c0565b6101ad610355366004611171565b61076a565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f61038f3660046111f9565b610778565b6101c16103a236600461126c565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610184604051806040016040528060018152602001603160f81b81525081565b6060600380546103fc9061129f565b80601f01602080910402602001604051908101604052809291908181526020018280546104289061129f565b80156104755780601f1061044a57610100808354040283529160200191610475565b820191906000526020600020905b81548152906001019060200180831161045857829003601f168201915b5050505050905090565b60003361048d8185856109fd565b60019150505b92915050565b6000336104a7858285610b56565b6104b2858585610be8565b506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146104f4576104ef46610dff565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061048d90829086906105539087906112ef565b6109fd565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105fb5760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106058282610eab565b5050565b6060600480546103fc9061129f565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106b65760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084016105f2565b6106058282610f8a565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091908381101561075d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016105f2565b6104b282868684036109fd565b60003361048d818585610be8565b834211156107ed5760405162461bcd60e51b8152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d69740000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661083a83611302565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e00160405160208183030381529060405280519060200120905060006108986104bd565b6040517f1901000000000000000000000000000000000000000000000000000000000000602082015260228101919091526042810183905260620160408051601f198184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa15801561093e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906109745750896001600160a01b0316816001600160a01b0316145b6109e65760405162461bcd60e51b815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e61747572650000000000000000000000000000000000000000000000000060648201526084016105f2565b6109f18a8a8a6109fd565b50505050505050505050565b6001600160a01b038316610a785760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216610af45760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610be25781811015610bd55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105f2565b610be284848484036109fd565b50505050565b6001600160a01b038316610c645760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216610ce05760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03831660009081526020819052604090205481811015610d6f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610da69084906112ef565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610df291815260200190565b60405180910390a3610be2565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e2a6103ed565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6001600160a01b038216610f015760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105f2565b8060026000828254610f1391906112ef565b90915550506001600160a01b03821660009081526020819052604081208054839290610f409084906112ef565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0382166110065760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b038216600090815260208190526040902054818110156110955760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016105f2565b6001600160a01b03831660009081526020819052604081208383039055600280548492906110c490849061131b565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b49565b600060208083528351808285015260005b8181101561113457858101830151858201604001528201611118565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461116c57600080fd5b919050565b6000806040838503121561118457600080fd5b61118d83611155565b946020939093013593505050565b6000806000606084860312156111b057600080fd5b6111b984611155565b92506111c760208501611155565b9150604084013590509250925092565b6000602082840312156111e957600080fd5b6111f282611155565b9392505050565b600080600080600080600060e0888a03121561121457600080fd5b61121d88611155565b965061122b60208901611155565b95506040880135945060608801359350608088013560ff8116811461124f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561127f57600080fd5b61128883611155565b915061129660208401611155565b90509250929050565b600181811c908216806112b357607f821691505b6020821081036112d357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610493576104936112d9565b600060018201611314576113146112d9565b5060010190565b81810381811115610493576104936112d956fea264697066735822122096b785fb92e9d4372a52fbc641ca1490dd9eca1990f97279973ebfb2e360d35264736f6c63430008110033a26469706673582212203e56a8c8e90f8393064aa68599de6b13ecf8da3fea75bef5ecea9d2366baca9264736f6c63430008110033", +} + +// PolygonzkevmbridgeABI is the input ABI used to generate the binding from. +// Deprecated: Use PolygonzkevmbridgeMetaData.ABI instead. +var PolygonzkevmbridgeABI = PolygonzkevmbridgeMetaData.ABI + +// PolygonzkevmbridgeBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use PolygonzkevmbridgeMetaData.Bin instead. +var PolygonzkevmbridgeBin = PolygonzkevmbridgeMetaData.Bin + +// DeployPolygonzkevmbridge deploys a new Ethereum contract, binding an instance of Polygonzkevmbridge to it. +func DeployPolygonzkevmbridge(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Polygonzkevmbridge, error) { + parsed, err := PolygonzkevmbridgeMetaData.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(PolygonzkevmbridgeBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Polygonzkevmbridge{PolygonzkevmbridgeCaller: PolygonzkevmbridgeCaller{contract: contract}, PolygonzkevmbridgeTransactor: PolygonzkevmbridgeTransactor{contract: contract}, PolygonzkevmbridgeFilterer: PolygonzkevmbridgeFilterer{contract: contract}}, nil +} + +// Polygonzkevmbridge is an auto generated Go binding around an Ethereum contract. +type Polygonzkevmbridge struct { + PolygonzkevmbridgeCaller // Read-only binding to the contract + PolygonzkevmbridgeTransactor // Write-only binding to the contract + PolygonzkevmbridgeFilterer // Log filterer for contract events +} + +// PolygonzkevmbridgeCaller is an auto generated read-only Go binding around an Ethereum contract. +type PolygonzkevmbridgeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmbridgeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PolygonzkevmbridgeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmbridgeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PolygonzkevmbridgeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmbridgeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PolygonzkevmbridgeSession struct { + Contract *Polygonzkevmbridge // 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 +} + +// PolygonzkevmbridgeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PolygonzkevmbridgeCallerSession struct { + Contract *PolygonzkevmbridgeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PolygonzkevmbridgeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PolygonzkevmbridgeTransactorSession struct { + Contract *PolygonzkevmbridgeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PolygonzkevmbridgeRaw is an auto generated low-level Go binding around an Ethereum contract. +type PolygonzkevmbridgeRaw struct { + Contract *Polygonzkevmbridge // Generic contract binding to access the raw methods on +} + +// PolygonzkevmbridgeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PolygonzkevmbridgeCallerRaw struct { + Contract *PolygonzkevmbridgeCaller // Generic read-only contract binding to access the raw methods on +} + +// PolygonzkevmbridgeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PolygonzkevmbridgeTransactorRaw struct { + Contract *PolygonzkevmbridgeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPolygonzkevmbridge creates a new instance of Polygonzkevmbridge, bound to a specific deployed contract. +func NewPolygonzkevmbridge(address common.Address, backend bind.ContractBackend) (*Polygonzkevmbridge, error) { + contract, err := bindPolygonzkevmbridge(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Polygonzkevmbridge{PolygonzkevmbridgeCaller: PolygonzkevmbridgeCaller{contract: contract}, PolygonzkevmbridgeTransactor: PolygonzkevmbridgeTransactor{contract: contract}, PolygonzkevmbridgeFilterer: PolygonzkevmbridgeFilterer{contract: contract}}, nil +} + +// NewPolygonzkevmbridgeCaller creates a new read-only instance of Polygonzkevmbridge, bound to a specific deployed contract. +func NewPolygonzkevmbridgeCaller(address common.Address, caller bind.ContractCaller) (*PolygonzkevmbridgeCaller, error) { + contract, err := bindPolygonzkevmbridge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeCaller{contract: contract}, nil +} + +// NewPolygonzkevmbridgeTransactor creates a new write-only instance of Polygonzkevmbridge, bound to a specific deployed contract. +func NewPolygonzkevmbridgeTransactor(address common.Address, transactor bind.ContractTransactor) (*PolygonzkevmbridgeTransactor, error) { + contract, err := bindPolygonzkevmbridge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeTransactor{contract: contract}, nil +} + +// NewPolygonzkevmbridgeFilterer creates a new log filterer instance of Polygonzkevmbridge, bound to a specific deployed contract. +func NewPolygonzkevmbridgeFilterer(address common.Address, filterer bind.ContractFilterer) (*PolygonzkevmbridgeFilterer, error) { + contract, err := bindPolygonzkevmbridge(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeFilterer{contract: contract}, nil +} + +// bindPolygonzkevmbridge binds a generic wrapper to an already deployed contract. +func bindPolygonzkevmbridge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PolygonzkevmbridgeMetaData.GetAbi() + 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 (_Polygonzkevmbridge *PolygonzkevmbridgeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevmbridge.Contract.PolygonzkevmbridgeCaller.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 (_Polygonzkevmbridge *PolygonzkevmbridgeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.PolygonzkevmbridgeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevmbridge *PolygonzkevmbridgeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.PolygonzkevmbridgeTransactor.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 (_Polygonzkevmbridge *PolygonzkevmbridgeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevmbridge.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 (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.contract.Transact(opts, method, params...) +} + +// ClaimedBitMap is a free data retrieval call binding the contract method 0xee25560b. +// +// Solidity: function claimedBitMap(uint256 ) view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) ClaimedBitMap(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "claimedBitMap", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ClaimedBitMap is a free data retrieval call binding the contract method 0xee25560b. +// +// Solidity: function claimedBitMap(uint256 ) view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) ClaimedBitMap(arg0 *big.Int) (*big.Int, error) { + return _Polygonzkevmbridge.Contract.ClaimedBitMap(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// ClaimedBitMap is a free data retrieval call binding the contract method 0xee25560b. +// +// Solidity: function claimedBitMap(uint256 ) view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) ClaimedBitMap(arg0 *big.Int) (*big.Int, error) { + return _Polygonzkevmbridge.Contract.ClaimedBitMap(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. +// +// Solidity: function depositCount() view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) DepositCount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "depositCount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. +// +// Solidity: function depositCount() view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) DepositCount() (*big.Int, error) { + return _Polygonzkevmbridge.Contract.DepositCount(&_Polygonzkevmbridge.CallOpts) +} + +// DepositCount is a free data retrieval call binding the contract method 0x2dfdf0b5. +// +// Solidity: function depositCount() view returns(uint256) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) DepositCount() (*big.Int, error) { + return _Polygonzkevmbridge.Contract.DepositCount(&_Polygonzkevmbridge.CallOpts) +} + +// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. +// +// Solidity: function getDepositRoot() view returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) GetDepositRoot(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "getDepositRoot") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. +// +// Solidity: function getDepositRoot() view returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) GetDepositRoot() ([32]byte, error) { + return _Polygonzkevmbridge.Contract.GetDepositRoot(&_Polygonzkevmbridge.CallOpts) +} + +// GetDepositRoot is a free data retrieval call binding the contract method 0x3ae05047. +// +// Solidity: function getDepositRoot() view returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) GetDepositRoot() ([32]byte, error) { + return _Polygonzkevmbridge.Contract.GetDepositRoot(&_Polygonzkevmbridge.CallOpts) +} + +// GetLeafValue is a free data retrieval call binding the contract method 0x3e197043. +// +// Solidity: function getLeafValue(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) GetLeafValue(opts *bind.CallOpts, leafType uint8, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "getLeafValue", leafType, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadataHash) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetLeafValue is a free data retrieval call binding the contract method 0x3e197043. +// +// Solidity: function getLeafValue(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) GetLeafValue(leafType uint8, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { + return _Polygonzkevmbridge.Contract.GetLeafValue(&_Polygonzkevmbridge.CallOpts, leafType, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadataHash) +} + +// GetLeafValue is a free data retrieval call binding the contract method 0x3e197043. +// +// Solidity: function getLeafValue(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes32 metadataHash) pure returns(bytes32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) GetLeafValue(leafType uint8, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadataHash [32]byte) ([32]byte, error) { + return _Polygonzkevmbridge.Contract.GetLeafValue(&_Polygonzkevmbridge.CallOpts, leafType, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadataHash) +} + +// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. +// +// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) GetTokenWrappedAddress(opts *bind.CallOpts, originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "getTokenWrappedAddress", originNetwork, originTokenAddress) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. +// +// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) GetTokenWrappedAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { + return _Polygonzkevmbridge.Contract.GetTokenWrappedAddress(&_Polygonzkevmbridge.CallOpts, originNetwork, originTokenAddress) +} + +// GetTokenWrappedAddress is a free data retrieval call binding the contract method 0x22e95f2c. +// +// Solidity: function getTokenWrappedAddress(uint32 originNetwork, address originTokenAddress) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) GetTokenWrappedAddress(originNetwork uint32, originTokenAddress common.Address) (common.Address, error) { + return _Polygonzkevmbridge.Contract.GetTokenWrappedAddress(&_Polygonzkevmbridge.CallOpts, originNetwork, originTokenAddress) +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) GlobalExitRootManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "globalExitRootManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) GlobalExitRootManager() (common.Address, error) { + return _Polygonzkevmbridge.Contract.GlobalExitRootManager(&_Polygonzkevmbridge.CallOpts) +} + +// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. +// +// Solidity: function globalExitRootManager() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) GlobalExitRootManager() (common.Address, error) { + return _Polygonzkevmbridge.Contract.GlobalExitRootManager(&_Polygonzkevmbridge.CallOpts) +} + +// IsClaimed is a free data retrieval call binding the contract method 0x9e34070f. +// +// Solidity: function isClaimed(uint256 index) view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) IsClaimed(opts *bind.CallOpts, index *big.Int) (bool, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "isClaimed", index) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsClaimed is a free data retrieval call binding the contract method 0x9e34070f. +// +// Solidity: function isClaimed(uint256 index) view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) IsClaimed(index *big.Int) (bool, error) { + return _Polygonzkevmbridge.Contract.IsClaimed(&_Polygonzkevmbridge.CallOpts, index) +} + +// IsClaimed is a free data retrieval call binding the contract method 0x9e34070f. +// +// Solidity: function isClaimed(uint256 index) view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) IsClaimed(index *big.Int) (bool, error) { + return _Polygonzkevmbridge.Contract.IsClaimed(&_Polygonzkevmbridge.CallOpts, index) +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) IsEmergencyState(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "isEmergencyState") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) IsEmergencyState() (bool, error) { + return _Polygonzkevmbridge.Contract.IsEmergencyState(&_Polygonzkevmbridge.CallOpts) +} + +// IsEmergencyState is a free data retrieval call binding the contract method 0x15064c96. +// +// Solidity: function isEmergencyState() view returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) IsEmergencyState() (bool, error) { + return _Polygonzkevmbridge.Contract.IsEmergencyState(&_Polygonzkevmbridge.CallOpts) +} + +// LastUpdatedDepositCount is a free data retrieval call binding the contract method 0xbe5831c7. +// +// Solidity: function lastUpdatedDepositCount() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) LastUpdatedDepositCount(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "lastUpdatedDepositCount") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// LastUpdatedDepositCount is a free data retrieval call binding the contract method 0xbe5831c7. +// +// Solidity: function lastUpdatedDepositCount() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) LastUpdatedDepositCount() (uint32, error) { + return _Polygonzkevmbridge.Contract.LastUpdatedDepositCount(&_Polygonzkevmbridge.CallOpts) +} + +// LastUpdatedDepositCount is a free data retrieval call binding the contract method 0xbe5831c7. +// +// Solidity: function lastUpdatedDepositCount() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) LastUpdatedDepositCount() (uint32, error) { + return _Polygonzkevmbridge.Contract.LastUpdatedDepositCount(&_Polygonzkevmbridge.CallOpts) +} + +// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. +// +// Solidity: function networkID() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) NetworkID(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "networkID") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. +// +// Solidity: function networkID() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) NetworkID() (uint32, error) { + return _Polygonzkevmbridge.Contract.NetworkID(&_Polygonzkevmbridge.CallOpts) +} + +// NetworkID is a free data retrieval call binding the contract method 0xbab161bf. +// +// Solidity: function networkID() view returns(uint32) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) NetworkID() (uint32, error) { + return _Polygonzkevmbridge.Contract.NetworkID(&_Polygonzkevmbridge.CallOpts) +} + +// PolygonZkEVMaddress is a free data retrieval call binding the contract method 0x34ac9cf2. +// +// Solidity: function polygonZkEVMaddress() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) PolygonZkEVMaddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "polygonZkEVMaddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// PolygonZkEVMaddress is a free data retrieval call binding the contract method 0x34ac9cf2. +// +// Solidity: function polygonZkEVMaddress() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) PolygonZkEVMaddress() (common.Address, error) { + return _Polygonzkevmbridge.Contract.PolygonZkEVMaddress(&_Polygonzkevmbridge.CallOpts) +} + +// PolygonZkEVMaddress is a free data retrieval call binding the contract method 0x34ac9cf2. +// +// Solidity: function polygonZkEVMaddress() view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) PolygonZkEVMaddress() (common.Address, error) { + return _Polygonzkevmbridge.Contract.PolygonZkEVMaddress(&_Polygonzkevmbridge.CallOpts) +} + +// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xaaa13cc2. +// +// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress, string name, string symbol, uint8 decimals) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) PrecalculatedWrapperAddress(opts *bind.CallOpts, originNetwork uint32, originTokenAddress common.Address, name string, symbol string, decimals uint8) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "precalculatedWrapperAddress", originNetwork, originTokenAddress, name, symbol, decimals) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xaaa13cc2. +// +// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress, string name, string symbol, uint8 decimals) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) PrecalculatedWrapperAddress(originNetwork uint32, originTokenAddress common.Address, name string, symbol string, decimals uint8) (common.Address, error) { + return _Polygonzkevmbridge.Contract.PrecalculatedWrapperAddress(&_Polygonzkevmbridge.CallOpts, originNetwork, originTokenAddress, name, symbol, decimals) +} + +// PrecalculatedWrapperAddress is a free data retrieval call binding the contract method 0xaaa13cc2. +// +// Solidity: function precalculatedWrapperAddress(uint32 originNetwork, address originTokenAddress, string name, string symbol, uint8 decimals) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) PrecalculatedWrapperAddress(originNetwork uint32, originTokenAddress common.Address, name string, symbol string, decimals uint8) (common.Address, error) { + return _Polygonzkevmbridge.Contract.PrecalculatedWrapperAddress(&_Polygonzkevmbridge.CallOpts, originNetwork, originTokenAddress, name, symbol, decimals) +} + +// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. +// +// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) TokenInfoToWrappedToken(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "tokenInfoToWrappedToken", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. +// +// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) TokenInfoToWrappedToken(arg0 [32]byte) (common.Address, error) { + return _Polygonzkevmbridge.Contract.TokenInfoToWrappedToken(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// TokenInfoToWrappedToken is a free data retrieval call binding the contract method 0x81b1c174. +// +// Solidity: function tokenInfoToWrappedToken(bytes32 ) view returns(address) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) TokenInfoToWrappedToken(arg0 [32]byte) (common.Address, error) { + return _Polygonzkevmbridge.Contract.TokenInfoToWrappedToken(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// VerifyMerkleProof is a free data retrieval call binding the contract method 0xfb570834. +// +// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[32] smtProof, uint32 index, bytes32 root) pure returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) VerifyMerkleProof(opts *bind.CallOpts, leafHash [32]byte, smtProof [32][32]byte, index uint32, root [32]byte) (bool, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "verifyMerkleProof", leafHash, smtProof, index, root) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// VerifyMerkleProof is a free data retrieval call binding the contract method 0xfb570834. +// +// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[32] smtProof, uint32 index, bytes32 root) pure returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) VerifyMerkleProof(leafHash [32]byte, smtProof [32][32]byte, index uint32, root [32]byte) (bool, error) { + return _Polygonzkevmbridge.Contract.VerifyMerkleProof(&_Polygonzkevmbridge.CallOpts, leafHash, smtProof, index, root) +} + +// VerifyMerkleProof is a free data retrieval call binding the contract method 0xfb570834. +// +// Solidity: function verifyMerkleProof(bytes32 leafHash, bytes32[32] smtProof, uint32 index, bytes32 root) pure returns(bool) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) VerifyMerkleProof(leafHash [32]byte, smtProof [32][32]byte, index uint32, root [32]byte) (bool, error) { + return _Polygonzkevmbridge.Contract.VerifyMerkleProof(&_Polygonzkevmbridge.CallOpts, leafHash, smtProof, index, root) +} + +// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. +// +// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) WrappedTokenToTokenInfo(opts *bind.CallOpts, arg0 common.Address) (struct { + OriginNetwork uint32 + OriginTokenAddress common.Address +}, error) { + var out []interface{} + err := _Polygonzkevmbridge.contract.Call(opts, &out, "wrappedTokenToTokenInfo", arg0) + + outstruct := new(struct { + OriginNetwork uint32 + OriginTokenAddress common.Address + }) + if err != nil { + return *outstruct, err + } + + outstruct.OriginNetwork = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.OriginTokenAddress = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. +// +// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) WrappedTokenToTokenInfo(arg0 common.Address) (struct { + OriginNetwork uint32 + OriginTokenAddress common.Address +}, error) { + return _Polygonzkevmbridge.Contract.WrappedTokenToTokenInfo(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// WrappedTokenToTokenInfo is a free data retrieval call binding the contract method 0x318aee3d. +// +// Solidity: function wrappedTokenToTokenInfo(address ) view returns(uint32 originNetwork, address originTokenAddress) +func (_Polygonzkevmbridge *PolygonzkevmbridgeCallerSession) WrappedTokenToTokenInfo(arg0 common.Address) (struct { + OriginNetwork uint32 + OriginTokenAddress common.Address +}, error) { + return _Polygonzkevmbridge.Contract.WrappedTokenToTokenInfo(&_Polygonzkevmbridge.CallOpts, arg0) +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x2072f6c5. +// +// Solidity: function activateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) ActivateEmergencyState(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "activateEmergencyState") +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x2072f6c5. +// +// Solidity: function activateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) ActivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ActivateEmergencyState(&_Polygonzkevmbridge.TransactOpts) +} + +// ActivateEmergencyState is a paid mutator transaction binding the contract method 0x2072f6c5. +// +// Solidity: function activateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) ActivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ActivateEmergencyState(&_Polygonzkevmbridge.TransactOpts) +} + +// BridgeAsset is a paid mutator transaction binding the contract method 0xcd586579. +// +// Solidity: function bridgeAsset(uint32 destinationNetwork, address destinationAddress, uint256 amount, address token, bool forceUpdateGlobalExitRoot, bytes permitData) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) BridgeAsset(opts *bind.TransactOpts, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, token common.Address, forceUpdateGlobalExitRoot bool, permitData []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "bridgeAsset", destinationNetwork, destinationAddress, amount, token, forceUpdateGlobalExitRoot, permitData) +} + +// BridgeAsset is a paid mutator transaction binding the contract method 0xcd586579. +// +// Solidity: function bridgeAsset(uint32 destinationNetwork, address destinationAddress, uint256 amount, address token, bool forceUpdateGlobalExitRoot, bytes permitData) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) BridgeAsset(destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, token common.Address, forceUpdateGlobalExitRoot bool, permitData []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.BridgeAsset(&_Polygonzkevmbridge.TransactOpts, destinationNetwork, destinationAddress, amount, token, forceUpdateGlobalExitRoot, permitData) +} + +// BridgeAsset is a paid mutator transaction binding the contract method 0xcd586579. +// +// Solidity: function bridgeAsset(uint32 destinationNetwork, address destinationAddress, uint256 amount, address token, bool forceUpdateGlobalExitRoot, bytes permitData) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) BridgeAsset(destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, token common.Address, forceUpdateGlobalExitRoot bool, permitData []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.BridgeAsset(&_Polygonzkevmbridge.TransactOpts, destinationNetwork, destinationAddress, amount, token, forceUpdateGlobalExitRoot, permitData) +} + +// BridgeMessage is a paid mutator transaction binding the contract method 0x240ff378. +// +// Solidity: function bridgeMessage(uint32 destinationNetwork, address destinationAddress, bool forceUpdateGlobalExitRoot, bytes metadata) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) BridgeMessage(opts *bind.TransactOpts, destinationNetwork uint32, destinationAddress common.Address, forceUpdateGlobalExitRoot bool, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "bridgeMessage", destinationNetwork, destinationAddress, forceUpdateGlobalExitRoot, metadata) +} + +// BridgeMessage is a paid mutator transaction binding the contract method 0x240ff378. +// +// Solidity: function bridgeMessage(uint32 destinationNetwork, address destinationAddress, bool forceUpdateGlobalExitRoot, bytes metadata) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) BridgeMessage(destinationNetwork uint32, destinationAddress common.Address, forceUpdateGlobalExitRoot bool, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.BridgeMessage(&_Polygonzkevmbridge.TransactOpts, destinationNetwork, destinationAddress, forceUpdateGlobalExitRoot, metadata) +} + +// BridgeMessage is a paid mutator transaction binding the contract method 0x240ff378. +// +// Solidity: function bridgeMessage(uint32 destinationNetwork, address destinationAddress, bool forceUpdateGlobalExitRoot, bytes metadata) payable returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) BridgeMessage(destinationNetwork uint32, destinationAddress common.Address, forceUpdateGlobalExitRoot bool, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.BridgeMessage(&_Polygonzkevmbridge.TransactOpts, destinationNetwork, destinationAddress, forceUpdateGlobalExitRoot, metadata) +} + +// ClaimAsset is a paid mutator transaction binding the contract method 0x2cffd02e. +// +// Solidity: function claimAsset(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) ClaimAsset(opts *bind.TransactOpts, smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "claimAsset", smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// ClaimAsset is a paid mutator transaction binding the contract method 0x2cffd02e. +// +// Solidity: function claimAsset(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) ClaimAsset(smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ClaimAsset(&_Polygonzkevmbridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// ClaimAsset is a paid mutator transaction binding the contract method 0x2cffd02e. +// +// Solidity: function claimAsset(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originTokenAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) ClaimAsset(smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originTokenAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ClaimAsset(&_Polygonzkevmbridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// ClaimMessage is a paid mutator transaction binding the contract method 0x2d2c9d94. +// +// Solidity: function claimMessage(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) ClaimMessage(opts *bind.TransactOpts, smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "claimMessage", smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// ClaimMessage is a paid mutator transaction binding the contract method 0x2d2c9d94. +// +// Solidity: function claimMessage(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) ClaimMessage(smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ClaimMessage(&_Polygonzkevmbridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// ClaimMessage is a paid mutator transaction binding the contract method 0x2d2c9d94. +// +// Solidity: function claimMessage(bytes32[32] smtProof, uint32 index, bytes32 mainnetExitRoot, bytes32 rollupExitRoot, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) ClaimMessage(smtProof [32][32]byte, index uint32, mainnetExitRoot [32]byte, rollupExitRoot [32]byte, originNetwork uint32, originAddress common.Address, destinationNetwork uint32, destinationAddress common.Address, amount *big.Int, metadata []byte) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.ClaimMessage(&_Polygonzkevmbridge.TransactOpts, smtProof, index, mainnetExitRoot, rollupExitRoot, originNetwork, originAddress, destinationNetwork, destinationAddress, amount, metadata) +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) DeactivateEmergencyState(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "deactivateEmergencyState") +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) DeactivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.DeactivateEmergencyState(&_Polygonzkevmbridge.TransactOpts) +} + +// DeactivateEmergencyState is a paid mutator transaction binding the contract method 0xdbc16976. +// +// Solidity: function deactivateEmergencyState() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) DeactivateEmergencyState() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.DeactivateEmergencyState(&_Polygonzkevmbridge.TransactOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0x647c576c. +// +// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager, address _polygonZkEVMaddress) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) Initialize(opts *bind.TransactOpts, _networkID uint32, _globalExitRootManager common.Address, _polygonZkEVMaddress common.Address) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "initialize", _networkID, _globalExitRootManager, _polygonZkEVMaddress) +} + +// Initialize is a paid mutator transaction binding the contract method 0x647c576c. +// +// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager, address _polygonZkEVMaddress) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) Initialize(_networkID uint32, _globalExitRootManager common.Address, _polygonZkEVMaddress common.Address) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.Initialize(&_Polygonzkevmbridge.TransactOpts, _networkID, _globalExitRootManager, _polygonZkEVMaddress) +} + +// Initialize is a paid mutator transaction binding the contract method 0x647c576c. +// +// Solidity: function initialize(uint32 _networkID, address _globalExitRootManager, address _polygonZkEVMaddress) returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) Initialize(_networkID uint32, _globalExitRootManager common.Address, _polygonZkEVMaddress common.Address) (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.Initialize(&_Polygonzkevmbridge.TransactOpts, _networkID, _globalExitRootManager, _polygonZkEVMaddress) +} + +// UpdateGlobalExitRoot is a paid mutator transaction binding the contract method 0x79e2cf97. +// +// Solidity: function updateGlobalExitRoot() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactor) UpdateGlobalExitRoot(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmbridge.contract.Transact(opts, "updateGlobalExitRoot") +} + +// UpdateGlobalExitRoot is a paid mutator transaction binding the contract method 0x79e2cf97. +// +// Solidity: function updateGlobalExitRoot() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeSession) UpdateGlobalExitRoot() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.UpdateGlobalExitRoot(&_Polygonzkevmbridge.TransactOpts) +} + +// UpdateGlobalExitRoot is a paid mutator transaction binding the contract method 0x79e2cf97. +// +// Solidity: function updateGlobalExitRoot() returns() +func (_Polygonzkevmbridge *PolygonzkevmbridgeTransactorSession) UpdateGlobalExitRoot() (*types.Transaction, error) { + return _Polygonzkevmbridge.Contract.UpdateGlobalExitRoot(&_Polygonzkevmbridge.TransactOpts) +} + +// PolygonzkevmbridgeBridgeEventIterator is returned from FilterBridgeEvent and is used to iterate over the raw logs and unpacked data for BridgeEvent events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeBridgeEventIterator struct { + Event *PolygonzkevmbridgeBridgeEvent // 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 *PolygonzkevmbridgeBridgeEventIterator) 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(PolygonzkevmbridgeBridgeEvent) + 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(PolygonzkevmbridgeBridgeEvent) + 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 *PolygonzkevmbridgeBridgeEventIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeBridgeEventIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeBridgeEvent represents a BridgeEvent event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeBridgeEvent struct { + LeafType uint8 + OriginNetwork uint32 + OriginAddress common.Address + DestinationNetwork uint32 + DestinationAddress common.Address + Amount *big.Int + Metadata []byte + DepositCount uint32 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBridgeEvent is a free log retrieval operation binding the contract event 0x501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b. +// +// Solidity: event BridgeEvent(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterBridgeEvent(opts *bind.FilterOpts) (*PolygonzkevmbridgeBridgeEventIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "BridgeEvent") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeBridgeEventIterator{contract: _Polygonzkevmbridge.contract, event: "BridgeEvent", logs: logs, sub: sub}, nil +} + +// WatchBridgeEvent is a free log subscription operation binding the contract event 0x501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b. +// +// Solidity: event BridgeEvent(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchBridgeEvent(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeBridgeEvent) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "BridgeEvent") + 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(PolygonzkevmbridgeBridgeEvent) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "BridgeEvent", 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 +} + +// ParseBridgeEvent is a log parse operation binding the contract event 0x501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b. +// +// Solidity: event BridgeEvent(uint8 leafType, uint32 originNetwork, address originAddress, uint32 destinationNetwork, address destinationAddress, uint256 amount, bytes metadata, uint32 depositCount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseBridgeEvent(log types.Log) (*PolygonzkevmbridgeBridgeEvent, error) { + event := new(PolygonzkevmbridgeBridgeEvent) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "BridgeEvent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmbridgeClaimEventIterator is returned from FilterClaimEvent and is used to iterate over the raw logs and unpacked data for ClaimEvent events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeClaimEventIterator struct { + Event *PolygonzkevmbridgeClaimEvent // 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 *PolygonzkevmbridgeClaimEventIterator) 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(PolygonzkevmbridgeClaimEvent) + 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(PolygonzkevmbridgeClaimEvent) + 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 *PolygonzkevmbridgeClaimEventIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeClaimEventIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeClaimEvent represents a ClaimEvent event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeClaimEvent struct { + Index uint32 + OriginNetwork uint32 + OriginAddress common.Address + DestinationAddress common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterClaimEvent is a free log retrieval operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. +// +// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originAddress, address destinationAddress, uint256 amount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterClaimEvent(opts *bind.FilterOpts) (*PolygonzkevmbridgeClaimEventIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "ClaimEvent") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeClaimEventIterator{contract: _Polygonzkevmbridge.contract, event: "ClaimEvent", logs: logs, sub: sub}, nil +} + +// WatchClaimEvent is a free log subscription operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. +// +// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originAddress, address destinationAddress, uint256 amount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchClaimEvent(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeClaimEvent) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "ClaimEvent") + 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(PolygonzkevmbridgeClaimEvent) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "ClaimEvent", 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 +} + +// ParseClaimEvent is a log parse operation binding the contract event 0x25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe27545983. +// +// Solidity: event ClaimEvent(uint32 index, uint32 originNetwork, address originAddress, address destinationAddress, uint256 amount) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseClaimEvent(log types.Log) (*PolygonzkevmbridgeClaimEvent, error) { + event := new(PolygonzkevmbridgeClaimEvent) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "ClaimEvent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmbridgeEmergencyStateActivatedIterator is returned from FilterEmergencyStateActivated and is used to iterate over the raw logs and unpacked data for EmergencyStateActivated events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeEmergencyStateActivatedIterator struct { + Event *PolygonzkevmbridgeEmergencyStateActivated // 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 *PolygonzkevmbridgeEmergencyStateActivatedIterator) 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(PolygonzkevmbridgeEmergencyStateActivated) + 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(PolygonzkevmbridgeEmergencyStateActivated) + 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 *PolygonzkevmbridgeEmergencyStateActivatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeEmergencyStateActivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeEmergencyStateActivated represents a EmergencyStateActivated event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeEmergencyStateActivated struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterEmergencyStateActivated is a free log retrieval operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterEmergencyStateActivated(opts *bind.FilterOpts) (*PolygonzkevmbridgeEmergencyStateActivatedIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "EmergencyStateActivated") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeEmergencyStateActivatedIterator{contract: _Polygonzkevmbridge.contract, event: "EmergencyStateActivated", logs: logs, sub: sub}, nil +} + +// WatchEmergencyStateActivated is a free log subscription operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchEmergencyStateActivated(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeEmergencyStateActivated) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "EmergencyStateActivated") + 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(PolygonzkevmbridgeEmergencyStateActivated) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "EmergencyStateActivated", 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 +} + +// ParseEmergencyStateActivated is a log parse operation binding the contract event 0x2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497. +// +// Solidity: event EmergencyStateActivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseEmergencyStateActivated(log types.Log) (*PolygonzkevmbridgeEmergencyStateActivated, error) { + event := new(PolygonzkevmbridgeEmergencyStateActivated) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "EmergencyStateActivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmbridgeEmergencyStateDeactivatedIterator is returned from FilterEmergencyStateDeactivated and is used to iterate over the raw logs and unpacked data for EmergencyStateDeactivated events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeEmergencyStateDeactivatedIterator struct { + Event *PolygonzkevmbridgeEmergencyStateDeactivated // 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 *PolygonzkevmbridgeEmergencyStateDeactivatedIterator) 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(PolygonzkevmbridgeEmergencyStateDeactivated) + 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(PolygonzkevmbridgeEmergencyStateDeactivated) + 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 *PolygonzkevmbridgeEmergencyStateDeactivatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeEmergencyStateDeactivatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeEmergencyStateDeactivated represents a EmergencyStateDeactivated event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeEmergencyStateDeactivated struct { + Raw types.Log // Blockchain specific contextual infos +} + +// FilterEmergencyStateDeactivated is a free log retrieval operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterEmergencyStateDeactivated(opts *bind.FilterOpts) (*PolygonzkevmbridgeEmergencyStateDeactivatedIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "EmergencyStateDeactivated") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeEmergencyStateDeactivatedIterator{contract: _Polygonzkevmbridge.contract, event: "EmergencyStateDeactivated", logs: logs, sub: sub}, nil +} + +// WatchEmergencyStateDeactivated is a free log subscription operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchEmergencyStateDeactivated(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeEmergencyStateDeactivated) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "EmergencyStateDeactivated") + 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(PolygonzkevmbridgeEmergencyStateDeactivated) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "EmergencyStateDeactivated", 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 +} + +// ParseEmergencyStateDeactivated is a log parse operation binding the contract event 0x1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3. +// +// Solidity: event EmergencyStateDeactivated() +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseEmergencyStateDeactivated(log types.Log) (*PolygonzkevmbridgeEmergencyStateDeactivated, error) { + event := new(PolygonzkevmbridgeEmergencyStateDeactivated) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "EmergencyStateDeactivated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmbridgeInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeInitializedIterator struct { + Event *PolygonzkevmbridgeInitialized // 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 *PolygonzkevmbridgeInitializedIterator) 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(PolygonzkevmbridgeInitialized) + 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(PolygonzkevmbridgeInitialized) + 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 *PolygonzkevmbridgeInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeInitialized represents a Initialized event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterInitialized(opts *bind.FilterOpts) (*PolygonzkevmbridgeInitializedIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeInitializedIterator{contract: _Polygonzkevmbridge.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeInitialized) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "Initialized") + 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(PolygonzkevmbridgeInitialized) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseInitialized(log types.Log) (*PolygonzkevmbridgeInitialized, error) { + event := new(PolygonzkevmbridgeInitialized) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// PolygonzkevmbridgeNewWrappedTokenIterator is returned from FilterNewWrappedToken and is used to iterate over the raw logs and unpacked data for NewWrappedToken events raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeNewWrappedTokenIterator struct { + Event *PolygonzkevmbridgeNewWrappedToken // 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 *PolygonzkevmbridgeNewWrappedTokenIterator) 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(PolygonzkevmbridgeNewWrappedToken) + 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(PolygonzkevmbridgeNewWrappedToken) + 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 *PolygonzkevmbridgeNewWrappedTokenIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmbridgeNewWrappedTokenIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmbridgeNewWrappedToken represents a NewWrappedToken event raised by the Polygonzkevmbridge contract. +type PolygonzkevmbridgeNewWrappedToken struct { + OriginNetwork uint32 + OriginTokenAddress common.Address + WrappedTokenAddress common.Address + Metadata []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNewWrappedToken is a free log retrieval operation binding the contract event 0x490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a39. +// +// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress, bytes metadata) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) FilterNewWrappedToken(opts *bind.FilterOpts) (*PolygonzkevmbridgeNewWrappedTokenIterator, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.FilterLogs(opts, "NewWrappedToken") + if err != nil { + return nil, err + } + return &PolygonzkevmbridgeNewWrappedTokenIterator{contract: _Polygonzkevmbridge.contract, event: "NewWrappedToken", logs: logs, sub: sub}, nil +} + +// WatchNewWrappedToken is a free log subscription operation binding the contract event 0x490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a39. +// +// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress, bytes metadata) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) WatchNewWrappedToken(opts *bind.WatchOpts, sink chan<- *PolygonzkevmbridgeNewWrappedToken) (event.Subscription, error) { + + logs, sub, err := _Polygonzkevmbridge.contract.WatchLogs(opts, "NewWrappedToken") + 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(PolygonzkevmbridgeNewWrappedToken) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "NewWrappedToken", 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 +} + +// ParseNewWrappedToken is a log parse operation binding the contract event 0x490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a39. +// +// Solidity: event NewWrappedToken(uint32 originNetwork, address originTokenAddress, address wrappedTokenAddress, bytes metadata) +func (_Polygonzkevmbridge *PolygonzkevmbridgeFilterer) ParseNewWrappedToken(log types.Log) (*PolygonzkevmbridgeNewWrappedToken, error) { + event := new(PolygonzkevmbridgeNewWrappedToken) + if err := _Polygonzkevmbridge.contract.UnpackLog(event, "NewWrappedToken", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/etherman/smartcontracts/polygonzkevmglobalexitroot/polygonzkevmglobalexitroot.go b/etherman/smartcontracts/polygonzkevmglobalexitroot/polygonzkevmglobalexitroot.go new file mode 100644 index 0000000000..19b37e2cca --- /dev/null +++ b/etherman/smartcontracts/polygonzkevmglobalexitroot/polygonzkevmglobalexitroot.go @@ -0,0 +1,563 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package polygonzkevmglobalexitroot + +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 + _ = abi.ConvertType +) + +// PolygonzkevmglobalexitrootMetaData contains all meta data concerning the Polygonzkevmglobalexitroot contract. +var PolygonzkevmglobalexitrootMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rollupAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_bridgeAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"OnlyAllowedContracts\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"mainnetExitRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"rollupExitRoot\",\"type\":\"bytes32\"}],\"name\":\"UpdateGlobalExitRoot\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"bridgeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastGlobalExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"globalExitRootMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMainnetExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRollupExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"newRoot\",\"type\":\"bytes32\"}],\"name\":\"updateExitRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60c060405234801561001057600080fd5b506040516103f83803806103f883398101604081905261002f91610062565b6001600160a01b0391821660a05216608052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a0516103316100c76000396000818160e901526101bd015260008181610135015261017401526103316000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806333d6247d1161005b57806333d6247d146100c75780633ed691ef146100dc5780635ec6a8df146100e4578063a3c573eb1461013057600080fd5b806301fd904414610082578063257b36321461009e578063319cf735146100be575b600080fd5b61008b60005481565b6040519081526020015b60405180910390f35b61008b6100ac3660046102e2565b60026020526000908152604090205481565b61008b60015481565b6100da6100d53660046102e2565b610157565b005b61008b6102a6565b61010b7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610095565b61010b7f000000000000000000000000000000000000000000000000000000000000000081565b60005460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101a65750600182905581610222565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101f0576000839055829150610222565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602080820184905281830185905282518083038401815260609092019092528051910120600090600081815260026020526040812054919250036102a05760008181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b60006102dd600154600054604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b6000602082840312156102f457600080fd5b503591905056fea26469706673582212209f4342d0e9635341e8c77469d3bc7ae71f0dddc6e79aebfb62c8bb1ad4fe68d664736f6c63430008110033", +} + +// PolygonzkevmglobalexitrootABI is the input ABI used to generate the binding from. +// Deprecated: Use PolygonzkevmglobalexitrootMetaData.ABI instead. +var PolygonzkevmglobalexitrootABI = PolygonzkevmglobalexitrootMetaData.ABI + +// PolygonzkevmglobalexitrootBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use PolygonzkevmglobalexitrootMetaData.Bin instead. +var PolygonzkevmglobalexitrootBin = PolygonzkevmglobalexitrootMetaData.Bin + +// DeployPolygonzkevmglobalexitroot deploys a new Ethereum contract, binding an instance of Polygonzkevmglobalexitroot to it. +func DeployPolygonzkevmglobalexitroot(auth *bind.TransactOpts, backend bind.ContractBackend, _rollupAddress common.Address, _bridgeAddress common.Address) (common.Address, *types.Transaction, *Polygonzkevmglobalexitroot, error) { + parsed, err := PolygonzkevmglobalexitrootMetaData.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(PolygonzkevmglobalexitrootBin), backend, _rollupAddress, _bridgeAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Polygonzkevmglobalexitroot{PolygonzkevmglobalexitrootCaller: PolygonzkevmglobalexitrootCaller{contract: contract}, PolygonzkevmglobalexitrootTransactor: PolygonzkevmglobalexitrootTransactor{contract: contract}, PolygonzkevmglobalexitrootFilterer: PolygonzkevmglobalexitrootFilterer{contract: contract}}, nil +} + +// Polygonzkevmglobalexitroot is an auto generated Go binding around an Ethereum contract. +type Polygonzkevmglobalexitroot struct { + PolygonzkevmglobalexitrootCaller // Read-only binding to the contract + PolygonzkevmglobalexitrootTransactor // Write-only binding to the contract + PolygonzkevmglobalexitrootFilterer // Log filterer for contract events +} + +// PolygonzkevmglobalexitrootCaller is an auto generated read-only Go binding around an Ethereum contract. +type PolygonzkevmglobalexitrootCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmglobalexitrootTransactor is an auto generated write-only Go binding around an Ethereum contract. +type PolygonzkevmglobalexitrootTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmglobalexitrootFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type PolygonzkevmglobalexitrootFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// PolygonzkevmglobalexitrootSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type PolygonzkevmglobalexitrootSession struct { + Contract *Polygonzkevmglobalexitroot // 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 +} + +// PolygonzkevmglobalexitrootCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type PolygonzkevmglobalexitrootCallerSession struct { + Contract *PolygonzkevmglobalexitrootCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// PolygonzkevmglobalexitrootTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type PolygonzkevmglobalexitrootTransactorSession struct { + Contract *PolygonzkevmglobalexitrootTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// PolygonzkevmglobalexitrootRaw is an auto generated low-level Go binding around an Ethereum contract. +type PolygonzkevmglobalexitrootRaw struct { + Contract *Polygonzkevmglobalexitroot // Generic contract binding to access the raw methods on +} + +// PolygonzkevmglobalexitrootCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type PolygonzkevmglobalexitrootCallerRaw struct { + Contract *PolygonzkevmglobalexitrootCaller // Generic read-only contract binding to access the raw methods on +} + +// PolygonzkevmglobalexitrootTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type PolygonzkevmglobalexitrootTransactorRaw struct { + Contract *PolygonzkevmglobalexitrootTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewPolygonzkevmglobalexitroot creates a new instance of Polygonzkevmglobalexitroot, bound to a specific deployed contract. +func NewPolygonzkevmglobalexitroot(address common.Address, backend bind.ContractBackend) (*Polygonzkevmglobalexitroot, error) { + contract, err := bindPolygonzkevmglobalexitroot(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Polygonzkevmglobalexitroot{PolygonzkevmglobalexitrootCaller: PolygonzkevmglobalexitrootCaller{contract: contract}, PolygonzkevmglobalexitrootTransactor: PolygonzkevmglobalexitrootTransactor{contract: contract}, PolygonzkevmglobalexitrootFilterer: PolygonzkevmglobalexitrootFilterer{contract: contract}}, nil +} + +// NewPolygonzkevmglobalexitrootCaller creates a new read-only instance of Polygonzkevmglobalexitroot, bound to a specific deployed contract. +func NewPolygonzkevmglobalexitrootCaller(address common.Address, caller bind.ContractCaller) (*PolygonzkevmglobalexitrootCaller, error) { + contract, err := bindPolygonzkevmglobalexitroot(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmglobalexitrootCaller{contract: contract}, nil +} + +// NewPolygonzkevmglobalexitrootTransactor creates a new write-only instance of Polygonzkevmglobalexitroot, bound to a specific deployed contract. +func NewPolygonzkevmglobalexitrootTransactor(address common.Address, transactor bind.ContractTransactor) (*PolygonzkevmglobalexitrootTransactor, error) { + contract, err := bindPolygonzkevmglobalexitroot(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PolygonzkevmglobalexitrootTransactor{contract: contract}, nil +} + +// NewPolygonzkevmglobalexitrootFilterer creates a new log filterer instance of Polygonzkevmglobalexitroot, bound to a specific deployed contract. +func NewPolygonzkevmglobalexitrootFilterer(address common.Address, filterer bind.ContractFilterer) (*PolygonzkevmglobalexitrootFilterer, error) { + contract, err := bindPolygonzkevmglobalexitroot(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PolygonzkevmglobalexitrootFilterer{contract: contract}, nil +} + +// bindPolygonzkevmglobalexitroot binds a generic wrapper to an already deployed contract. +func bindPolygonzkevmglobalexitroot(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PolygonzkevmglobalexitrootMetaData.GetAbi() + 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 (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevmglobalexitroot.Contract.PolygonzkevmglobalexitrootCaller.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 (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.PolygonzkevmglobalexitrootTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.PolygonzkevmglobalexitrootTransactor.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 (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Polygonzkevmglobalexitroot.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 (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.contract.Transact(opts, method, params...) +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) BridgeAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "bridgeAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) BridgeAddress() (common.Address, error) { + return _Polygonzkevmglobalexitroot.Contract.BridgeAddress(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// BridgeAddress is a free data retrieval call binding the contract method 0xa3c573eb. +// +// Solidity: function bridgeAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) BridgeAddress() (common.Address, error) { + return _Polygonzkevmglobalexitroot.Contract.BridgeAddress(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. +// +// Solidity: function getLastGlobalExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) GetLastGlobalExitRoot(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "getLastGlobalExitRoot") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. +// +// Solidity: function getLastGlobalExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) GetLastGlobalExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.GetLastGlobalExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// GetLastGlobalExitRoot is a free data retrieval call binding the contract method 0x3ed691ef. +// +// Solidity: function getLastGlobalExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) GetLastGlobalExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.GetLastGlobalExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. +// +// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) GlobalExitRootMap(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "globalExitRootMap", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. +// +// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) GlobalExitRootMap(arg0 [32]byte) (*big.Int, error) { + return _Polygonzkevmglobalexitroot.Contract.GlobalExitRootMap(&_Polygonzkevmglobalexitroot.CallOpts, arg0) +} + +// GlobalExitRootMap is a free data retrieval call binding the contract method 0x257b3632. +// +// Solidity: function globalExitRootMap(bytes32 ) view returns(uint256) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) GlobalExitRootMap(arg0 [32]byte) (*big.Int, error) { + return _Polygonzkevmglobalexitroot.Contract.GlobalExitRootMap(&_Polygonzkevmglobalexitroot.CallOpts, arg0) +} + +// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. +// +// Solidity: function lastMainnetExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) LastMainnetExitRoot(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "lastMainnetExitRoot") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. +// +// Solidity: function lastMainnetExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) LastMainnetExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.LastMainnetExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// LastMainnetExitRoot is a free data retrieval call binding the contract method 0x319cf735. +// +// Solidity: function lastMainnetExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) LastMainnetExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.LastMainnetExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. +// +// Solidity: function lastRollupExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) LastRollupExitRoot(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "lastRollupExitRoot") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. +// +// Solidity: function lastRollupExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) LastRollupExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.LastRollupExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// LastRollupExitRoot is a free data retrieval call binding the contract method 0x01fd9044. +// +// Solidity: function lastRollupExitRoot() view returns(bytes32) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) LastRollupExitRoot() ([32]byte, error) { + return _Polygonzkevmglobalexitroot.Contract.LastRollupExitRoot(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCaller) RollupAddress(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Polygonzkevmglobalexitroot.contract.Call(opts, &out, "rollupAddress") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) RollupAddress() (common.Address, error) { + return _Polygonzkevmglobalexitroot.Contract.RollupAddress(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// RollupAddress is a free data retrieval call binding the contract method 0x5ec6a8df. +// +// Solidity: function rollupAddress() view returns(address) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootCallerSession) RollupAddress() (common.Address, error) { + return _Polygonzkevmglobalexitroot.Contract.RollupAddress(&_Polygonzkevmglobalexitroot.CallOpts) +} + +// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. +// +// Solidity: function updateExitRoot(bytes32 newRoot) returns() +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootTransactor) UpdateExitRoot(opts *bind.TransactOpts, newRoot [32]byte) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.contract.Transact(opts, "updateExitRoot", newRoot) +} + +// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. +// +// Solidity: function updateExitRoot(bytes32 newRoot) returns() +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootSession) UpdateExitRoot(newRoot [32]byte) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.UpdateExitRoot(&_Polygonzkevmglobalexitroot.TransactOpts, newRoot) +} + +// UpdateExitRoot is a paid mutator transaction binding the contract method 0x33d6247d. +// +// Solidity: function updateExitRoot(bytes32 newRoot) returns() +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootTransactorSession) UpdateExitRoot(newRoot [32]byte) (*types.Transaction, error) { + return _Polygonzkevmglobalexitroot.Contract.UpdateExitRoot(&_Polygonzkevmglobalexitroot.TransactOpts, newRoot) +} + +// PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator is returned from FilterUpdateGlobalExitRoot and is used to iterate over the raw logs and unpacked data for UpdateGlobalExitRoot events raised by the Polygonzkevmglobalexitroot contract. +type PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator struct { + Event *PolygonzkevmglobalexitrootUpdateGlobalExitRoot // 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 *PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator) 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(PolygonzkevmglobalexitrootUpdateGlobalExitRoot) + 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(PolygonzkevmglobalexitrootUpdateGlobalExitRoot) + 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 *PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// PolygonzkevmglobalexitrootUpdateGlobalExitRoot represents a UpdateGlobalExitRoot event raised by the Polygonzkevmglobalexitroot contract. +type PolygonzkevmglobalexitrootUpdateGlobalExitRoot struct { + MainnetExitRoot [32]byte + RollupExitRoot [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpdateGlobalExitRoot is a free log retrieval operation binding the contract event 0x61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce3. +// +// Solidity: event UpdateGlobalExitRoot(bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootFilterer) FilterUpdateGlobalExitRoot(opts *bind.FilterOpts, mainnetExitRoot [][32]byte, rollupExitRoot [][32]byte) (*PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator, error) { + + var mainnetExitRootRule []interface{} + for _, mainnetExitRootItem := range mainnetExitRoot { + mainnetExitRootRule = append(mainnetExitRootRule, mainnetExitRootItem) + } + var rollupExitRootRule []interface{} + for _, rollupExitRootItem := range rollupExitRoot { + rollupExitRootRule = append(rollupExitRootRule, rollupExitRootItem) + } + + logs, sub, err := _Polygonzkevmglobalexitroot.contract.FilterLogs(opts, "UpdateGlobalExitRoot", mainnetExitRootRule, rollupExitRootRule) + if err != nil { + return nil, err + } + return &PolygonzkevmglobalexitrootUpdateGlobalExitRootIterator{contract: _Polygonzkevmglobalexitroot.contract, event: "UpdateGlobalExitRoot", logs: logs, sub: sub}, nil +} + +// WatchUpdateGlobalExitRoot is a free log subscription operation binding the contract event 0x61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce3. +// +// Solidity: event UpdateGlobalExitRoot(bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootFilterer) WatchUpdateGlobalExitRoot(opts *bind.WatchOpts, sink chan<- *PolygonzkevmglobalexitrootUpdateGlobalExitRoot, mainnetExitRoot [][32]byte, rollupExitRoot [][32]byte) (event.Subscription, error) { + + var mainnetExitRootRule []interface{} + for _, mainnetExitRootItem := range mainnetExitRoot { + mainnetExitRootRule = append(mainnetExitRootRule, mainnetExitRootItem) + } + var rollupExitRootRule []interface{} + for _, rollupExitRootItem := range rollupExitRoot { + rollupExitRootRule = append(rollupExitRootRule, rollupExitRootItem) + } + + logs, sub, err := _Polygonzkevmglobalexitroot.contract.WatchLogs(opts, "UpdateGlobalExitRoot", mainnetExitRootRule, rollupExitRootRule) + 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(PolygonzkevmglobalexitrootUpdateGlobalExitRoot) + if err := _Polygonzkevmglobalexitroot.contract.UnpackLog(event, "UpdateGlobalExitRoot", 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 +} + +// ParseUpdateGlobalExitRoot is a log parse operation binding the contract event 0x61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce3. +// +// Solidity: event UpdateGlobalExitRoot(bytes32 indexed mainnetExitRoot, bytes32 indexed rollupExitRoot) +func (_Polygonzkevmglobalexitroot *PolygonzkevmglobalexitrootFilterer) ParseUpdateGlobalExitRoot(log types.Log) (*PolygonzkevmglobalexitrootUpdateGlobalExitRoot, error) { + event := new(PolygonzkevmglobalexitrootUpdateGlobalExitRoot) + if err := _Polygonzkevmglobalexitroot.contract.UnpackLog(event, "UpdateGlobalExitRoot", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/etherman/smartcontracts/proofofefficiency/proofofefficiency.go b/etherman/smartcontracts/proofofefficiency/proofofefficiency.go deleted file mode 100644 index 5458b6fa10..0000000000 --- a/etherman/smartcontracts/proofofefficiency/proofofefficiency.go +++ /dev/null @@ -1,2191 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package proofofefficiency - -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 -) - -// ProofOfEfficiencyBatchData is an auto generated low-level Go binding around an user-defined struct. -type ProofOfEfficiencyBatchData struct { - Transactions []byte - GlobalExitRoot [32]byte - Timestamp uint64 - ForceBatchesTimestamp []uint64 -} - -// ProofofefficiencyMetaData contains all meta data concerning the Proofofefficiency contract. -var ProofofefficiencyMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"forceBatchNum\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"lastGlobalExitRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sequencer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"}],\"name\":\"ForceBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"}],\"name\":\"SequenceBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"}],\"name\":\"SequenceForceBatches\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newForceBatchAllowed\",\"type\":\"bool\"}],\"name\":\"SetForceBatchAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTrustedSequencer\",\"type\":\"address\"}],\"name\":\"SetTrustedSequencer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newTrustedSequencerURL\",\"type\":\"string\"}],\"name\":\"SetTrustedSequencerURL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"VerifyBatch\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FORCE_BATCH_TIMEOUT\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_BATCH_LENGTH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"TRUSTED_SEQUENCER_FEE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"calculateForceProverFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainID\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentLocalExitRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentStateRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maticAmount\",\"type\":\"uint256\"}],\"name\":\"forceBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"forceBatchAllowed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"forcedBatches\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"batchHashData\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maticFee\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"minTimestamp\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"globalExitRootManager\",\"outputs\":[{\"internalType\":\"contractIGlobalExitRootManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIGlobalExitRootManager\",\"name\":\"_globalExitRootManager\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Upgradeable\",\"name\":\"_matic\",\"type\":\"address\"},{\"internalType\":\"contractIVerifierRollup\",\"name\":\"_rollupVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"genesisRoot\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_trustedSequencer\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_forceBatchAllowed\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_trustedSequencerURL\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"_chainID\",\"type\":\"uint64\"},{\"internalType\":\"string\",\"name\":\"_networkName\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchSequenced\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastForceBatch\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastForceBatchSequenced\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastVerifiedBatch\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"matic\",\"outputs\":[{\"internalType\":\"contractIERC20Upgradeable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"networkName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupVerifier\",\"outputs\":[{\"internalType\":\"contractIVerifierRollup\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"transactions\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"globalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint64[]\",\"name\":\"forceBatchesTimestamp\",\"type\":\"uint64[]\"}],\"internalType\":\"structProofOfEfficiency.BatchData[]\",\"name\":\"batches\",\"type\":\"tuple[]\"}],\"name\":\"sequenceBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"numForcedBatches\",\"type\":\"uint64\"}],\"name\":\"sequenceForceBatches\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"sequencedBatches\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"batchHashData\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"forceBatchNum\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"newForceBatchAllowed\",\"type\":\"bool\"}],\"name\":\"setForceBatchAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTrustedSequencer\",\"type\":\"address\"}],\"name\":\"setTrustedSequencer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newTrustedSequencerURL\",\"type\":\"string\"}],\"name\":\"setTrustedSequencerURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedSequencer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedSequencerURL\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"newLocalExitRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"numBatch\",\"type\":\"uint64\"},{\"internalType\":\"uint256[2]\",\"name\":\"proofA\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2][2]\",\"name\":\"proofB\",\"type\":\"uint256[2][2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"proofC\",\"type\":\"uint256[2]\"}],\"name\":\"verifyBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50614a6d806100206000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c8063ac2eba9811610104578063d02103ca116100a2578063e8bf92ed11610071578063e8bf92ed146104de578063eaeb077b146104fc578063f755276114610518578063f7d2cd7f14610536576101cf565b8063d02103ca14610468578063d2fd1b3114610486578063d8f54db0146104a2578063e7a7ed02146104c0576101cf565b8063b4d63f58116100de578063b4d63f58146103de578063b6b0b09714610410578063c89e42df1461042e578063cfa8ed471461044a576101cf565b8063ac2eba9814610384578063adc879e9146103a2578063b02286c0146103c0576101cf565b8063798470571161017157806395297e241161014b57806395297e2414610310578063959c2f471461032c578063aa0f44181461034a578063ab9fc5ef14610366576101cf565b806379847057146102b85780637fcb3653146102d65780638c4a0af7146102f4576101cf565b806345605267116101ad578063456052671461022e578063542028d51461024c5780636b8616ce1461026a5780636ff512cc1461029c576101cf565b8063107bf28c146101d457806319d8ac61146101f2578063423fa85614610210575b600080fd5b6101dc610552565b6040516101e991906127ea565b60405180910390f35b6101fa6105e0565b604051610207919061282f565b60405180910390f35b6102186105fa565b604051610225919061282f565b60405180910390f35b610236610614565b604051610243919061282f565b60405180910390f35b61025461062e565b60405161026191906127ea565b60405180910390f35b610284600480360381019061027f919061288a565b6106bc565b604051610293939291906128e9565b60405180910390f35b6102b660048036038101906102b1919061297e565b6106fa565b005b6102c0610805565b6040516102cd91906129ab565b60405180910390f35b6102de61086d565b6040516102eb919061282f565b60405180910390f35b61030e600480360381019061030991906129fe565b610887565b005b61032a60048036038101906103259190612aa0565b61096b565b005b610334610f96565b6040516103419190612b2f565b60405180910390f35b610364600480360381019061035f919061288a565b610f9c565b005b61036e6113ac565b60405161037b919061282f565b60405180910390f35b61038c6113b3565b6040516103999190612b2f565b60405180910390f35b6103aa6113b9565b6040516103b7919061282f565b60405180910390f35b6103c86113d3565b6040516103d591906129ab565b60405180910390f35b6103f860048036038101906103f3919061288a565b6113d9565b60405161040793929190612b4a565b60405180910390f35b61041861142b565b6040516104259190612be0565b60405180910390f35b61044860048036038101906104439190612d30565b611451565b005b61045261152b565b60405161045f9190612d88565b60405180910390f35b610470611551565b60405161047d9190612dc4565b60405180910390f35b6104a0600480360381019061049b9190612e99565b611577565b005b6104aa611824565b6040516104b79190612faa565b60405180910390f35b6104c8611837565b6040516104d5919061282f565b60405180910390f35b6104e6611851565b6040516104f39190612fe6565b60405180910390f35b610516600480360381019061051191906130ce565b611877565b005b610520611ca2565b60405161052d91906129ab565b60405180910390f35b610550600480360381019061054b9190613388565b611cae565b005b600b805461055f90613400565b80601f016020809104026020016040519081016040528092919081815260200182805461058b90613400565b80156105d85780601f106105ad576101008083540402835291602001916105d8565b820191906000526020600020905b8154815290600101906020018083116105bb57829003601f168201915b505050505081565b600360009054906101000a900467ffffffffffffffff1681565b600360089054906101000a900467ffffffffffffffff1681565b600360109054906101000a900467ffffffffffffffff1681565b6009805461063b90613400565b80601f016020809104026020016040519081016040528092919081815260200182805461066790613400565b80156106b45780601f10610689576101008083540402835291602001916106b4565b820191906000526020600020905b81548152906001019060200180831161069757829003601f168201915b505050505081565b60016020528060005260406000206000915090508060000154908060010154908060020160009054906101000a900467ffffffffffffffff16905083565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461078a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610781906134a3565b60405180910390fd5b80600460086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0816040516107fa9190612d88565b60405180910390a150565b6000600360109054906101000a900467ffffffffffffffff16600360189054906101000a900467ffffffffffffffff16600161084191906134f2565b61084b9190613530565b67ffffffffffffffff16670de0b6b3a76400006108689190613564565b905090565b600460009054906101000a900467ffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610917576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090e906134a3565b60405180910390fd5b806004601c6101000a81548160ff0219169083151502179055507fbacda50a4a8575be1d91a7ebe29ee45056f3a94f12a2281eb6b43afa33bcefe6816040516109609190612faa565b60405180910390a150565b6001600460009054906101000a900467ffffffffffffffff1661098e91906134f2565b67ffffffffffffffff168467ffffffffffffffff16146109e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109da90613630565b60405180910390fd5b600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff168467ffffffffffffffff161115610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a47906136e8565b60405180910390fd5b6000600260008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160009054906101000a900467ffffffffffffffff1690506000806000600260008967ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1603610b2357600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060000154915067016345785d8a00009050610bed565b600060016000600260008b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160089054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060405180606001604052908160008201548152602001600182015481526020016002820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152505090508060000151925080602001519150505b60006006546007548a8c868c89600a60009054906101000a900467ffffffffffffffff16604051602001610c2898979695949392919061375f565b604051602081830303815290604052805190602001209050606060405190506054604082010160405260548152602081013360601b815260148101905060005b6008811015610c905783602082021c60e01b60201c8252600882019150600181019050610c68565b505060007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051610cc59190613838565b602060405180830381855afa158015610ce2573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610d059190613864565b60001c610d1291906138c0565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166343753b4d8a8a8a6040518060200160405280878152506040518563ffffffff1660e01b8152600401610d839493929190613a6b565b602060405180830381865afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613ac7565b610e03576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfa90613b66565b60405180910390fd5b6004600081819054906101000a900467ffffffffffffffff1680929190610e2990613b86565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508a6006819055508b600781905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333d6247d6007546040518263ffffffff1660e01b8152600401610ebb9190612b2f565b600060405180830381600087803b158015610ed557600080fd5b505af1158015610ee9573d6000803e3d6000fd5b50505050610f3a3385600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166123c59092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff168a67ffffffffffffffff167f2cdf1508085a46c7241a7d78c5a1ec3d9246d1ab95e1c2a33676d29e17d4222360405160405180910390a3505050505050505050505050565b60075481565b600115156004601c9054906101000a900460ff16151514610ff2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fe990613c4e565b60405180910390fd5b600081600360109054906101000a900467ffffffffffffffff1661101691906134f2565b905060008267ffffffffffffffff1611611065576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105c90613d06565b60405180910390fd5b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1611156110d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110c990613d98565b60405180910390fd5b600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111c1574262093a80600160008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900467ffffffffffffffff1661117591906134f2565b67ffffffffffffffff1611156111c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b790613e50565b60405180910390fd5b5b6000600360089054906101000a900467ffffffffffffffff1690506000600360109054906101000a900467ffffffffffffffff16905060005b8467ffffffffffffffff168110156112dd57818061121790613b86565b925050828061122590613b86565b93505081600260008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555042600260008567ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080806112d590613e70565b9150506111fa565b5042600360006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600360086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600360106101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff167f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a460405160405180910390a250505050565b62093a8081565b60065481565b600a60009054906101000a900467ffffffffffffffff1681565b61ea6081565b60026020528060005260406000206000915090508060000154908060010160009054906101000a900467ffffffffffffffff16908060010160089054906101000a900467ffffffffffffffff16905083565b600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d8906134a3565b60405180910390fd5b80600990816114f0919061405a565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b208160405161152091906127ea565b60405180910390a150565b600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060019054906101000a900460ff161590508080156115a85750600160008054906101000a900460ff1660ff16105b806115d557506115b73061244b565b1580156115d45750600160008054906101000a900460ff1660ff16145b5b611614576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160b9061419e565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015611651576001600060016101000a81548160ff0219169083151502179055505b89600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088600060026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508660068190555085600460086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846004601c6101000a81548160ff0219169083151502179055508360099081611785919061405a565b5082600a60006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600b90816117be919061405a565b5080156118185760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405161180f9190614206565b60405180910390a15b50505050505050505050565b6004601c9054906101000a900460ff1681565b600360189054906101000a900467ffffffffffffffff1681565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600115156004601c9054906101000a900460ff161515146118cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c490613c4e565b60405180910390fd5b60006118d7610805565b90508181111561191c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191390614293565b60405180910390fd5b61ea60835110611961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195890614325565b60405180910390fd5b6119b0333083600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661246e909392919063ffffffff16565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a439190613864565b90506003601881819054906101000a900467ffffffffffffffff1680929190611a6b90613b86565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050838133604051602001611aa79392919061438d565b6040516020818303038152906040528051906020012060016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600001819055508160016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600101819055504260016000600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603611c3f57600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9318233604051611c329291906143fd565b60405180910390a2611c9c565b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823387604051611c9393929190614472565b60405180910390a25b50505050565b67016345785d8a000081565b3373ffffffffffffffffffffffffffffffffffffffff16600460089054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611d3e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d35906134a3565b60405180910390fd5b600081519050611da633308367016345785d8a0000611d5d9190613564565b600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661246e909392919063ffffffff16565b6000600360009054906101000a900467ffffffffffffffff1690506000600360089054906101000a900467ffffffffffffffff1690506000600360109054906101000a900467ffffffffffffffff16905060005b84811015612288576000868281518110611e1757611e166144b0565b5b602002602001015190508467ffffffffffffffff16816040015167ffffffffffffffff1610158015611e57575042816040015167ffffffffffffffff1611155b611e96576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8d90614577565b60405180910390fd5b6000801b81602001511480611f4d57506000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663257b363283602001516040518263ffffffff1660e01b8152600401611f079190612b2f565b6020604051808303816000875af1158015611f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4a91906145ac565b14155b611f8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f839061464b565b60405180910390fd5b61ea6081600001515110611fd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcc906146dd565b60405180910390fd5b8380611fe090613b86565b94505080600001518160200151336040516020016120009392919061438d565b60405160208183030381529060405280519060200120600260008667ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020600001819055508060400151600260008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508060400151945060005b8160600151518110156122735783806120bb90613b86565b9450506000826060015182815181106120d7576120d66144b0565b5b602002602001015190508667ffffffffffffffff168167ffffffffffffffff16101580156121575750600160008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1610155b801561216d5750428167ffffffffffffffff1611155b6121ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a390614795565b60405180910390fd5b85806121b790613b86565b96505084600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600260008867ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080965050808061226b90613e70565b9150506120a3565b5050808061228090613e70565b915050611dfa565b50600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168167ffffffffffffffff1611156122f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122ed90614827565b60405180910390fd5b82600360006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555081600360086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555080600360106101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600360089054906101000a900467ffffffffffffffff1667ffffffffffffffff167f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce60405160405180910390a25050505050565b6124468363a9059cbb60e01b84846040516024016123e4929190614847565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124f7565b505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6124f1846323b872dd60e01b85858560405160240161248f93929190614870565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506124f7565b50505050565b6000612559826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125be9092919063ffffffff16565b90506000815111156125b957808060200190518101906125799190613ac7565b6125b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125af90614919565b60405180910390fd5b5b505050565b60606125cd84846000856125d6565b90509392505050565b60608247101561261b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612612906149ab565b60405180910390fd5b6126248561244b565b612663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265a90614a17565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161268c9190613838565b60006040518083038185875af1925050503d80600081146126c9576040519150601f19603f3d011682016040523d82523d6000602084013e6126ce565b606091505b50915091506126de8282866126ea565b92505050949350505050565b606083156126fa5782905061274a565b60008351111561270d5782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161274191906127ea565b60405180910390fd5b9392505050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561278b578082015181840152602081019050612770565b8381111561279a576000848401525b50505050565b6000601f19601f8301169050919050565b60006127bc82612751565b6127c6818561275c565b93506127d681856020860161276d565b6127df816127a0565b840191505092915050565b6000602082019050818103600083015261280481846127b1565b905092915050565b600067ffffffffffffffff82169050919050565b6128298161280c565b82525050565b60006020820190506128446000830184612820565b92915050565b6000604051905090565b600080fd5b600080fd5b6128678161280c565b811461287257600080fd5b50565b6000813590506128848161285e565b92915050565b6000602082840312156128a05761289f612854565b5b60006128ae84828501612875565b91505092915050565b6000819050919050565b6128ca816128b7565b82525050565b6000819050919050565b6128e3816128d0565b82525050565b60006060820190506128fe60008301866128c1565b61290b60208301856128da565b6129186040830184612820565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061294b82612920565b9050919050565b61295b81612940565b811461296657600080fd5b50565b60008135905061297881612952565b92915050565b60006020828403121561299457612993612854565b5b60006129a284828501612969565b91505092915050565b60006020820190506129c060008301846128da565b92915050565b60008115159050919050565b6129db816129c6565b81146129e657600080fd5b50565b6000813590506129f8816129d2565b92915050565b600060208284031215612a1457612a13612854565b5b6000612a22848285016129e9565b91505092915050565b612a34816128b7565b8114612a3f57600080fd5b50565b600081359050612a5181612a2b565b92915050565b600080fd5b600081905082602060020282011115612a7857612a77612a57565b5b92915050565b600081905082604060020282011115612a9a57612a99612a57565b5b92915050565b6000806000806000806101608789031215612abe57612abd612854565b5b6000612acc89828a01612a42565b9650506020612add89828a01612a42565b9550506040612aee89828a01612875565b9450506060612aff89828a01612a5c565b93505060a0612b1089828a01612a7e565b925050610120612b2289828a01612a5c565b9150509295509295509295565b6000602082019050612b4460008301846128c1565b92915050565b6000606082019050612b5f60008301866128c1565b612b6c6020830185612820565b612b796040830184612820565b949350505050565b6000819050919050565b6000612ba6612ba1612b9c84612920565b612b81565b612920565b9050919050565b6000612bb882612b8b565b9050919050565b6000612bca82612bad565b9050919050565b612bda81612bbf565b82525050565b6000602082019050612bf56000830184612bd1565b92915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612c3d826127a0565b810181811067ffffffffffffffff82111715612c5c57612c5b612c05565b5b80604052505050565b6000612c6f61284a565b9050612c7b8282612c34565b919050565b600067ffffffffffffffff821115612c9b57612c9a612c05565b5b612ca4826127a0565b9050602081019050919050565b82818337600083830152505050565b6000612cd3612cce84612c80565b612c65565b905082815260208101848484011115612cef57612cee612c00565b5b612cfa848285612cb1565b509392505050565b600082601f830112612d1757612d16612bfb565b5b8135612d27848260208601612cc0565b91505092915050565b600060208284031215612d4657612d45612854565b5b600082013567ffffffffffffffff811115612d6457612d63612859565b5b612d7084828501612d02565b91505092915050565b612d8281612940565b82525050565b6000602082019050612d9d6000830184612d79565b92915050565b6000612dae82612bad565b9050919050565b612dbe81612da3565b82525050565b6000602082019050612dd96000830184612db5565b92915050565b6000612dea82612940565b9050919050565b612dfa81612ddf565b8114612e0557600080fd5b50565b600081359050612e1781612df1565b92915050565b6000612e2882612940565b9050919050565b612e3881612e1d565b8114612e4357600080fd5b50565b600081359050612e5581612e2f565b92915050565b6000612e6682612940565b9050919050565b612e7681612e5b565b8114612e8157600080fd5b50565b600081359050612e9381612e6d565b92915050565b60008060008060008060008060006101208a8c031215612ebc57612ebb612854565b5b6000612eca8c828d01612e08565b9950506020612edb8c828d01612e46565b9850506040612eec8c828d01612e84565b9750506060612efd8c828d01612a42565b9650506080612f0e8c828d01612969565b95505060a0612f1f8c828d016129e9565b94505060c08a013567ffffffffffffffff811115612f4057612f3f612859565b5b612f4c8c828d01612d02565b93505060e0612f5d8c828d01612875565b9250506101008a013567ffffffffffffffff811115612f7f57612f7e612859565b5b612f8b8c828d01612d02565b9150509295985092959850929598565b612fa4816129c6565b82525050565b6000602082019050612fbf6000830184612f9b565b92915050565b6000612fd082612bad565b9050919050565b612fe081612fc5565b82525050565b6000602082019050612ffb6000830184612fd7565b92915050565b600067ffffffffffffffff82111561301c5761301b612c05565b5b613025826127a0565b9050602081019050919050565b600061304561304084613001565b612c65565b90508281526020810184848401111561306157613060612c00565b5b61306c848285612cb1565b509392505050565b600082601f83011261308957613088612bfb565b5b8135613099848260208601613032565b91505092915050565b6130ab816128d0565b81146130b657600080fd5b50565b6000813590506130c8816130a2565b92915050565b600080604083850312156130e5576130e4612854565b5b600083013567ffffffffffffffff81111561310357613102612859565b5b61310f85828601613074565b9250506020613120858286016130b9565b9150509250929050565b600067ffffffffffffffff82111561314557613144612c05565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff82111561317b5761317a612c05565b5b602082029050602081019050919050565b600061319f61319a84613160565b612c65565b905080838252602082019050602084028301858111156131c2576131c1612a57565b5b835b818110156131eb57806131d78882612875565b8452602084019350506020810190506131c4565b5050509392505050565b600082601f83011261320a57613209612bfb565b5b813561321a84826020860161318c565b91505092915050565b60006080828403121561323957613238613156565b5b6132436080612c65565b9050600082013567ffffffffffffffff8111156132635761326261315b565b5b61326f84828501613074565b600083015250602061328384828501612a42565b602083015250604061329784828501612875565b604083015250606082013567ffffffffffffffff8111156132bb576132ba61315b565b5b6132c7848285016131f5565b60608301525092915050565b60006132e66132e18461312a565b612c65565b9050808382526020820190506020840283018581111561330957613308612a57565b5b835b8181101561335057803567ffffffffffffffff81111561332e5761332d612bfb565b5b80860161333b8982613223565b8552602085019450505060208101905061330b565b5050509392505050565b600082601f83011261336f5761336e612bfb565b5b813561337f8482602086016132d3565b91505092915050565b60006020828403121561339e5761339d612854565b5b600082013567ffffffffffffffff8111156133bc576133bb612859565b5b6133c88482850161335a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061341857607f821691505b60208210810361342b5761342a6133d1565b5b50919050565b7f50726f6f664f66456666696369656e63793a3a6f6e6c7954727573746564536560008201527f7175656e6365723a206f6e6c7920747275737465642073657175656e63657200602082015250565b600061348d603f8361275c565b915061349882613431565b604082019050919050565b600060208201905081810360008301526134bc81613480565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006134fd8261280c565b91506135088361280c565b92508267ffffffffffffffff03821115613525576135246134c3565b5b828201905092915050565b600061353b8261280c565b91506135468361280c565b925082821015613559576135586134c3565b5b828203905092915050565b600061356f826128d0565b915061357a836128d0565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156135b3576135b26134c3565b5b828202905092915050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f626174636820646f6573206e6f74206d61746368000000000000000000000000602082015250565b600061361a60348361275c565b9150613625826135be565b604082019050919050565b600060208201905081810360008301526136498161360d565b9050919050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f626174636820646f6573206e6f742068617665206265656e2073657175656e6360208201527f6564000000000000000000000000000000000000000000000000000000000000604082015250565b60006136d260428361275c565b91506136dd82613650565b606082019050919050565b60006020820190508181036000830152613701816136c5565b9050919050565b6000819050919050565b61372361371e826128b7565b613708565b82525050565b60008160c01b9050919050565b600061374182613729565b9050919050565b6137596137548261280c565b613736565b82525050565b600061376b828b613712565b60208201915061377b828a613712565b60208201915061378b8289613712565b60208201915061379b8288613712565b6020820191506137ab8287613712565b6020820191506137bb8286613748565b6008820191506137cb8285613748565b6008820191506137db8284613748565b6008820191508190509998505050505050505050565b600081519050919050565b600081905092915050565b6000613812826137f1565b61381c81856137fc565b935061382c81856020860161276d565b80840191505092915050565b60006138448284613807565b915081905092915050565b60008151905061385e81612a2b565b92915050565b60006020828403121561387a57613879612854565b5b60006138888482850161384f565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006138cb826128d0565b91506138d6836128d0565b9250826138e6576138e5613891565b5b828206905092915050565b6138fd60408383612cb1565b5050565b600060029050919050565b600081905092915050565b6000819050919050565b61392d60408383612cb1565b5050565b600061393d8383613921565b60408301905092915050565b600082905092915050565b6000604082019050919050565b61396a81613901565b613974818461390c565b925061397f82613917565b8060005b838110156139b8576139958284613949565b61399f8782613931565b96506139aa83613954565b925050600181019050613983565b505050505050565b600060019050919050565b600081905092915050565b6000819050919050565b6139e9816128d0565b82525050565b60006139fb83836139e0565b60208301905092915050565b6000602082019050919050565b613a1d816139c0565b613a2781846139cb565b9250613a32826139d6565b8060005b83811015613a63578151613a4a87826139ef565b9650613a5583613a07565b925050600181019050613a36565b505050505050565b600061012082019050613a8160008301876138f1565b613a8e6040830186613961565b613a9b60c08301856138f1565b613aa9610100830184613a14565b95945050505050565b600081519050613ac1816129d2565b92915050565b600060208284031215613add57613adc612854565b5b6000613aeb84828501613ab2565b91505092915050565b7f50726f6f664f66456666696369656e63793a3a76657269667942617463683a2060008201527f494e56414c49445f50524f4f4600000000000000000000000000000000000000602082015250565b6000613b50602d8361275c565b9150613b5b82613af4565b604082019050919050565b60006020820190508181036000830152613b7f81613b43565b9050919050565b6000613b918261280c565b915067ffffffffffffffff8203613bab57613baa6134c3565b5b600182019050919050565b7f50726f6f664f66456666696369656e63793a3a6973466f72636542617463684160008201527f6c6c6f7765643a206f6e6c7920696620666f726365206261746368206973206160208201527f7661696c61626c65000000000000000000000000000000000000000000000000604082015250565b6000613c3860488361275c565b9150613c4382613bb6565b606082019050919050565b60006020820190508181036000830152613c6781613c2b565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a204d75737420666f726365206174206c6561737420312062617460208201527f6368000000000000000000000000000000000000000000000000000000000000604082015250565b6000613cf060428361275c565b9150613cfb82613c6e565b606082019050919050565b60006020820190508181036000830152613d1f81613ce3565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a20466f72636520626174636820696e76616c6964000000000000602082015250565b6000613d82603a8361275c565b9150613d8d82613d26565b604082019050919050565b60006020820190508181036000830152613db181613d75565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365466f72636560008201527f42617463683a20466f72636564206261746368206973206e6f7420696e20746960208201527f6d656f757420706572696f640000000000000000000000000000000000000000604082015250565b6000613e3a604c8361275c565b9150613e4582613db8565b606082019050919050565b60006020820190508181036000830152613e6981613e2d565b9050919050565b6000613e7b826128d0565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ead57613eac6134c3565b5b600182019050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613f1a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613edd565b613f248683613edd565b95508019841693508086168417925050509392505050565b6000613f57613f52613f4d846128d0565b612b81565b6128d0565b9050919050565b6000819050919050565b613f7183613f3c565b613f85613f7d82613f5e565b848454613eea565b825550505050565b600090565b613f9a613f8d565b613fa5818484613f68565b505050565b5b81811015613fc957613fbe600082613f92565b600181019050613fab565b5050565b601f82111561400e57613fdf81613eb8565b613fe884613ecd565b81016020851015613ff7578190505b61400b61400385613ecd565b830182613faa565b50505b505050565b600082821c905092915050565b600061403160001984600802614013565b1980831691505092915050565b600061404a8383614020565b9150826002028217905092915050565b61406382612751565b67ffffffffffffffff81111561407c5761407b612c05565b5b6140868254613400565b614091828285613fcd565b600060209050601f8311600181146140c457600084156140b2578287015190505b6140bc858261403e565b865550614124565b601f1984166140d286613eb8565b60005b828110156140fa578489015182556001820191506020850194506020810190506140d5565b868310156141175784890151614113601f891682614020565b8355505b6001600288020188555050505b505050505050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000614188602e8361275c565b91506141938261412c565b604082019050919050565b600060208201905081810360008301526141b78161417b565b9050919050565b6000819050919050565b600060ff82169050919050565b60006141f06141eb6141e6846141be565b612b81565b6141c8565b9050919050565b614200816141d5565b82525050565b600060208201905061421b60008301846141f7565b92915050565b7f50726f6f664f66456666696369656e63793a3a666f72636542617463683a206e60008201527f6f7420656e6f756768206d617469630000000000000000000000000000000000602082015250565b600061427d602f8361275c565b915061428882614221565b604082019050919050565b600060208201905081810360008301526142ac81614270565b9050919050565b7f50726f6f664f66456666696369656e63793a3a666f72636542617463683a205460008201527f72616e73616374696f6e73206279746573206f766572666c6f77000000000000602082015250565b600061430f603a8361275c565b915061431a826142b3565b604082019050919050565b6000602082019050818103600083015261433e81614302565b9050919050565b60008160601b9050919050565b600061435d82614345565b9050919050565b600061436f82614352565b9050919050565b61438761438282612940565b614364565b82525050565b60006143998286613807565b91506143a58285613712565b6020820191506143b58284614376565b601482019150819050949350505050565b600082825260208201905092915050565b50565b60006143e76000836143c6565b91506143f2826143d7565b600082019050919050565b600060608201905061441260008301856128c1565b61441f6020830184612d79565b8181036040830152614430816143da565b90509392505050565b6000614444826137f1565b61444e81856143c6565b935061445e81856020860161276d565b614467816127a0565b840191505092915050565b600060608201905061448760008301866128c1565b6144946020830185612d79565b81810360408301526144a68184614439565b9050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a2054696d657374616d70206d75737420626520696e736964652072616e60208201527f6765000000000000000000000000000000000000000000000000000000000000604082015250565b600061456160428361275c565b915061456c826144df565b606082019050919050565b6000602082019050818103600083015261459081614554565b9050919050565b6000815190506145a6816130a2565b92915050565b6000602082840312156145c2576145c1612854565b5b60006145d084828501614597565b91505092915050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20476c6f62616c206578697420726f6f74206d75737420657869737400602082015250565b6000614635603f8361275c565b9150614640826145d9565b604082019050919050565b6000602082019050818103600083015261466481614628565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a205472616e73616374696f6e73206279746573206f766572666c6f7700602082015250565b60006146c7603f8361275c565b91506146d28261466b565b604082019050919050565b600060208201905081810360008301526146f6816146ba565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20466f7263656420626174636865732074696d657374616d70206d757360208201527f7420626520696e736964652072616e6765000000000000000000000000000000604082015250565b600061477f60518361275c565b915061478a826146fd565b606082019050919050565b600060208201905081810360008301526147ae81614772565b9050919050565b7f50726f6f664f66456666696369656e63793a3a73657175656e6365426174636860008201527f65733a20466f7263652062617463686573206f766572666c6f77000000000000602082015250565b6000614811603a8361275c565b915061481c826147b5565b604082019050919050565b6000602082019050818103600083015261484081614804565b9050919050565b600060408201905061485c6000830185612d79565b61486960208301846128da565b9392505050565b60006060820190506148856000830186612d79565b6148926020830185612d79565b61489f60408301846128da565b949350505050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b6000614903602a8361275c565b915061490e826148a7565b604082019050919050565b60006020820190508181036000830152614932816148f6565b9050919050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b600061499560268361275c565b91506149a082614939565b604082019050919050565b600060208201905081810360008301526149c481614988565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000614a01601d8361275c565b9150614a0c826149cb565b602082019050919050565b60006020820190508181036000830152614a30816149f4565b905091905056fea264697066735822122096d3f605efd2603a322512eaacca9427459d9f6977009f0fce10ca96f79f16da64736f6c634300080f0033", -} - -// ProofofefficiencyABI is the input ABI used to generate the binding from. -// Deprecated: Use ProofofefficiencyMetaData.ABI instead. -var ProofofefficiencyABI = ProofofefficiencyMetaData.ABI - -// ProofofefficiencyBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ProofofefficiencyMetaData.Bin instead. -var ProofofefficiencyBin = ProofofefficiencyMetaData.Bin - -// DeployProofofefficiency deploys a new Ethereum contract, binding an instance of Proofofefficiency to it. -func DeployProofofefficiency(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Proofofefficiency, error) { - parsed, err := ProofofefficiencyMetaData.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(ProofofefficiencyBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Proofofefficiency{ProofofefficiencyCaller: ProofofefficiencyCaller{contract: contract}, ProofofefficiencyTransactor: ProofofefficiencyTransactor{contract: contract}, ProofofefficiencyFilterer: ProofofefficiencyFilterer{contract: contract}}, nil -} - -// Proofofefficiency is an auto generated Go binding around an Ethereum contract. -type Proofofefficiency struct { - ProofofefficiencyCaller // Read-only binding to the contract - ProofofefficiencyTransactor // Write-only binding to the contract - ProofofefficiencyFilterer // Log filterer for contract events -} - -// ProofofefficiencyCaller is an auto generated read-only Go binding around an Ethereum contract. -type ProofofefficiencyCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ProofofefficiencyTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ProofofefficiencyTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ProofofefficiencyFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ProofofefficiencyFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ProofofefficiencySession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ProofofefficiencySession struct { - Contract *Proofofefficiency // 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 -} - -// ProofofefficiencyCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ProofofefficiencyCallerSession struct { - Contract *ProofofefficiencyCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ProofofefficiencyTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ProofofefficiencyTransactorSession struct { - Contract *ProofofefficiencyTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ProofofefficiencyRaw is an auto generated low-level Go binding around an Ethereum contract. -type ProofofefficiencyRaw struct { - Contract *Proofofefficiency // Generic contract binding to access the raw methods on -} - -// ProofofefficiencyCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ProofofefficiencyCallerRaw struct { - Contract *ProofofefficiencyCaller // Generic read-only contract binding to access the raw methods on -} - -// ProofofefficiencyTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ProofofefficiencyTransactorRaw struct { - Contract *ProofofefficiencyTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewProofofefficiency creates a new instance of Proofofefficiency, bound to a specific deployed contract. -func NewProofofefficiency(address common.Address, backend bind.ContractBackend) (*Proofofefficiency, error) { - contract, err := bindProofofefficiency(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Proofofefficiency{ProofofefficiencyCaller: ProofofefficiencyCaller{contract: contract}, ProofofefficiencyTransactor: ProofofefficiencyTransactor{contract: contract}, ProofofefficiencyFilterer: ProofofefficiencyFilterer{contract: contract}}, nil -} - -// NewProofofefficiencyCaller creates a new read-only instance of Proofofefficiency, bound to a specific deployed contract. -func NewProofofefficiencyCaller(address common.Address, caller bind.ContractCaller) (*ProofofefficiencyCaller, error) { - contract, err := bindProofofefficiency(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ProofofefficiencyCaller{contract: contract}, nil -} - -// NewProofofefficiencyTransactor creates a new write-only instance of Proofofefficiency, bound to a specific deployed contract. -func NewProofofefficiencyTransactor(address common.Address, transactor bind.ContractTransactor) (*ProofofefficiencyTransactor, error) { - contract, err := bindProofofefficiency(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ProofofefficiencyTransactor{contract: contract}, nil -} - -// NewProofofefficiencyFilterer creates a new log filterer instance of Proofofefficiency, bound to a specific deployed contract. -func NewProofofefficiencyFilterer(address common.Address, filterer bind.ContractFilterer) (*ProofofefficiencyFilterer, error) { - contract, err := bindProofofefficiency(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ProofofefficiencyFilterer{contract: contract}, nil -} - -// bindProofofefficiency binds a generic wrapper to an already deployed contract. -func bindProofofefficiency(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ProofofefficiencyABI)) - 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 (_Proofofefficiency *ProofofefficiencyRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Proofofefficiency.Contract.ProofofefficiencyCaller.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 (_Proofofefficiency *ProofofefficiencyRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Proofofefficiency.Contract.ProofofefficiencyTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Proofofefficiency *ProofofefficiencyRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Proofofefficiency.Contract.ProofofefficiencyTransactor.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 (_Proofofefficiency *ProofofefficiencyCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Proofofefficiency.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 (_Proofofefficiency *ProofofefficiencyTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Proofofefficiency.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Proofofefficiency *ProofofefficiencyTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Proofofefficiency.Contract.contract.Transact(opts, method, params...) -} - -// FORCEBATCHTIMEOUT is a free data retrieval call binding the contract method 0xab9fc5ef. -// -// Solidity: function FORCE_BATCH_TIMEOUT() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) FORCEBATCHTIMEOUT(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "FORCE_BATCH_TIMEOUT") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// FORCEBATCHTIMEOUT is a free data retrieval call binding the contract method 0xab9fc5ef. -// -// Solidity: function FORCE_BATCH_TIMEOUT() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) FORCEBATCHTIMEOUT() (uint64, error) { - return _Proofofefficiency.Contract.FORCEBATCHTIMEOUT(&_Proofofefficiency.CallOpts) -} - -// FORCEBATCHTIMEOUT is a free data retrieval call binding the contract method 0xab9fc5ef. -// -// Solidity: function FORCE_BATCH_TIMEOUT() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) FORCEBATCHTIMEOUT() (uint64, error) { - return _Proofofefficiency.Contract.FORCEBATCHTIMEOUT(&_Proofofefficiency.CallOpts) -} - -// MAXBATCHLENGTH is a free data retrieval call binding the contract method 0xb02286c0. -// -// Solidity: function MAX_BATCH_LENGTH() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCaller) MAXBATCHLENGTH(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "MAX_BATCH_LENGTH") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// MAXBATCHLENGTH is a free data retrieval call binding the contract method 0xb02286c0. -// -// Solidity: function MAX_BATCH_LENGTH() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencySession) MAXBATCHLENGTH() (*big.Int, error) { - return _Proofofefficiency.Contract.MAXBATCHLENGTH(&_Proofofefficiency.CallOpts) -} - -// MAXBATCHLENGTH is a free data retrieval call binding the contract method 0xb02286c0. -// -// Solidity: function MAX_BATCH_LENGTH() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCallerSession) MAXBATCHLENGTH() (*big.Int, error) { - return _Proofofefficiency.Contract.MAXBATCHLENGTH(&_Proofofefficiency.CallOpts) -} - -// TRUSTEDSEQUENCERFEE is a free data retrieval call binding the contract method 0xf7552761. -// -// Solidity: function TRUSTED_SEQUENCER_FEE() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCaller) TRUSTEDSEQUENCERFEE(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "TRUSTED_SEQUENCER_FEE") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// TRUSTEDSEQUENCERFEE is a free data retrieval call binding the contract method 0xf7552761. -// -// Solidity: function TRUSTED_SEQUENCER_FEE() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencySession) TRUSTEDSEQUENCERFEE() (*big.Int, error) { - return _Proofofefficiency.Contract.TRUSTEDSEQUENCERFEE(&_Proofofefficiency.CallOpts) -} - -// TRUSTEDSEQUENCERFEE is a free data retrieval call binding the contract method 0xf7552761. -// -// Solidity: function TRUSTED_SEQUENCER_FEE() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCallerSession) TRUSTEDSEQUENCERFEE() (*big.Int, error) { - return _Proofofefficiency.Contract.TRUSTEDSEQUENCERFEE(&_Proofofefficiency.CallOpts) -} - -// CalculateForceProverFee is a free data retrieval call binding the contract method 0x79847057. -// -// Solidity: function calculateForceProverFee() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCaller) CalculateForceProverFee(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "calculateForceProverFee") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// CalculateForceProverFee is a free data retrieval call binding the contract method 0x79847057. -// -// Solidity: function calculateForceProverFee() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencySession) CalculateForceProverFee() (*big.Int, error) { - return _Proofofefficiency.Contract.CalculateForceProverFee(&_Proofofefficiency.CallOpts) -} - -// CalculateForceProverFee is a free data retrieval call binding the contract method 0x79847057. -// -// Solidity: function calculateForceProverFee() view returns(uint256) -func (_Proofofefficiency *ProofofefficiencyCallerSession) CalculateForceProverFee() (*big.Int, error) { - return _Proofofefficiency.Contract.CalculateForceProverFee(&_Proofofefficiency.CallOpts) -} - -// ChainID is a free data retrieval call binding the contract method 0xadc879e9. -// -// Solidity: function chainID() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) ChainID(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "chainID") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// ChainID is a free data retrieval call binding the contract method 0xadc879e9. -// -// Solidity: function chainID() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) ChainID() (uint64, error) { - return _Proofofefficiency.Contract.ChainID(&_Proofofefficiency.CallOpts) -} - -// ChainID is a free data retrieval call binding the contract method 0xadc879e9. -// -// Solidity: function chainID() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) ChainID() (uint64, error) { - return _Proofofefficiency.Contract.ChainID(&_Proofofefficiency.CallOpts) -} - -// CurrentLocalExitRoot is a free data retrieval call binding the contract method 0x959c2f47. -// -// Solidity: function currentLocalExitRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencyCaller) CurrentLocalExitRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "currentLocalExitRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// CurrentLocalExitRoot is a free data retrieval call binding the contract method 0x959c2f47. -// -// Solidity: function currentLocalExitRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencySession) CurrentLocalExitRoot() ([32]byte, error) { - return _Proofofefficiency.Contract.CurrentLocalExitRoot(&_Proofofefficiency.CallOpts) -} - -// CurrentLocalExitRoot is a free data retrieval call binding the contract method 0x959c2f47. -// -// Solidity: function currentLocalExitRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencyCallerSession) CurrentLocalExitRoot() ([32]byte, error) { - return _Proofofefficiency.Contract.CurrentLocalExitRoot(&_Proofofefficiency.CallOpts) -} - -// CurrentStateRoot is a free data retrieval call binding the contract method 0xac2eba98. -// -// Solidity: function currentStateRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencyCaller) CurrentStateRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "currentStateRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// CurrentStateRoot is a free data retrieval call binding the contract method 0xac2eba98. -// -// Solidity: function currentStateRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencySession) CurrentStateRoot() ([32]byte, error) { - return _Proofofefficiency.Contract.CurrentStateRoot(&_Proofofefficiency.CallOpts) -} - -// CurrentStateRoot is a free data retrieval call binding the contract method 0xac2eba98. -// -// Solidity: function currentStateRoot() view returns(bytes32) -func (_Proofofefficiency *ProofofefficiencyCallerSession) CurrentStateRoot() ([32]byte, error) { - return _Proofofefficiency.Contract.CurrentStateRoot(&_Proofofefficiency.CallOpts) -} - -// ForceBatchAllowed is a free data retrieval call binding the contract method 0xd8f54db0. -// -// Solidity: function forceBatchAllowed() view returns(bool) -func (_Proofofefficiency *ProofofefficiencyCaller) ForceBatchAllowed(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "forceBatchAllowed") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// ForceBatchAllowed is a free data retrieval call binding the contract method 0xd8f54db0. -// -// Solidity: function forceBatchAllowed() view returns(bool) -func (_Proofofefficiency *ProofofefficiencySession) ForceBatchAllowed() (bool, error) { - return _Proofofefficiency.Contract.ForceBatchAllowed(&_Proofofefficiency.CallOpts) -} - -// ForceBatchAllowed is a free data retrieval call binding the contract method 0xd8f54db0. -// -// Solidity: function forceBatchAllowed() view returns(bool) -func (_Proofofefficiency *ProofofefficiencyCallerSession) ForceBatchAllowed() (bool, error) { - return _Proofofefficiency.Contract.ForceBatchAllowed(&_Proofofefficiency.CallOpts) -} - -// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. -// -// Solidity: function forcedBatches(uint64 ) view returns(bytes32 batchHashData, uint256 maticFee, uint64 minTimestamp) -func (_Proofofefficiency *ProofofefficiencyCaller) ForcedBatches(opts *bind.CallOpts, arg0 uint64) (struct { - BatchHashData [32]byte - MaticFee *big.Int - MinTimestamp uint64 -}, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "forcedBatches", arg0) - - outstruct := new(struct { - BatchHashData [32]byte - MaticFee *big.Int - MinTimestamp uint64 - }) - if err != nil { - return *outstruct, err - } - - outstruct.BatchHashData = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - outstruct.MaticFee = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - outstruct.MinTimestamp = *abi.ConvertType(out[2], new(uint64)).(*uint64) - - return *outstruct, err - -} - -// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. -// -// Solidity: function forcedBatches(uint64 ) view returns(bytes32 batchHashData, uint256 maticFee, uint64 minTimestamp) -func (_Proofofefficiency *ProofofefficiencySession) ForcedBatches(arg0 uint64) (struct { - BatchHashData [32]byte - MaticFee *big.Int - MinTimestamp uint64 -}, error) { - return _Proofofefficiency.Contract.ForcedBatches(&_Proofofefficiency.CallOpts, arg0) -} - -// ForcedBatches is a free data retrieval call binding the contract method 0x6b8616ce. -// -// Solidity: function forcedBatches(uint64 ) view returns(bytes32 batchHashData, uint256 maticFee, uint64 minTimestamp) -func (_Proofofefficiency *ProofofefficiencyCallerSession) ForcedBatches(arg0 uint64) (struct { - BatchHashData [32]byte - MaticFee *big.Int - MinTimestamp uint64 -}, error) { - return _Proofofefficiency.Contract.ForcedBatches(&_Proofofefficiency.CallOpts, arg0) -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCaller) GlobalExitRootManager(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "globalExitRootManager") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Proofofefficiency *ProofofefficiencySession) GlobalExitRootManager() (common.Address, error) { - return _Proofofefficiency.Contract.GlobalExitRootManager(&_Proofofefficiency.CallOpts) -} - -// GlobalExitRootManager is a free data retrieval call binding the contract method 0xd02103ca. -// -// Solidity: function globalExitRootManager() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCallerSession) GlobalExitRootManager() (common.Address, error) { - return _Proofofefficiency.Contract.GlobalExitRootManager(&_Proofofefficiency.CallOpts) -} - -// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. -// -// Solidity: function lastBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) LastBatchSequenced(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "lastBatchSequenced") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. -// -// Solidity: function lastBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) LastBatchSequenced() (uint64, error) { - return _Proofofefficiency.Contract.LastBatchSequenced(&_Proofofefficiency.CallOpts) -} - -// LastBatchSequenced is a free data retrieval call binding the contract method 0x423fa856. -// -// Solidity: function lastBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) LastBatchSequenced() (uint64, error) { - return _Proofofefficiency.Contract.LastBatchSequenced(&_Proofofefficiency.CallOpts) -} - -// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. -// -// Solidity: function lastForceBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) LastForceBatch(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "lastForceBatch") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. -// -// Solidity: function lastForceBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) LastForceBatch() (uint64, error) { - return _Proofofefficiency.Contract.LastForceBatch(&_Proofofefficiency.CallOpts) -} - -// LastForceBatch is a free data retrieval call binding the contract method 0xe7a7ed02. -// -// Solidity: function lastForceBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) LastForceBatch() (uint64, error) { - return _Proofofefficiency.Contract.LastForceBatch(&_Proofofefficiency.CallOpts) -} - -// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. -// -// Solidity: function lastForceBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) LastForceBatchSequenced(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "lastForceBatchSequenced") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. -// -// Solidity: function lastForceBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) LastForceBatchSequenced() (uint64, error) { - return _Proofofefficiency.Contract.LastForceBatchSequenced(&_Proofofefficiency.CallOpts) -} - -// LastForceBatchSequenced is a free data retrieval call binding the contract method 0x45605267. -// -// Solidity: function lastForceBatchSequenced() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) LastForceBatchSequenced() (uint64, error) { - return _Proofofefficiency.Contract.LastForceBatchSequenced(&_Proofofefficiency.CallOpts) -} - -// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. -// -// Solidity: function lastTimestamp() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) LastTimestamp(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "lastTimestamp") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. -// -// Solidity: function lastTimestamp() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) LastTimestamp() (uint64, error) { - return _Proofofefficiency.Contract.LastTimestamp(&_Proofofefficiency.CallOpts) -} - -// LastTimestamp is a free data retrieval call binding the contract method 0x19d8ac61. -// -// Solidity: function lastTimestamp() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) LastTimestamp() (uint64, error) { - return _Proofofefficiency.Contract.LastTimestamp(&_Proofofefficiency.CallOpts) -} - -// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. -// -// Solidity: function lastVerifiedBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCaller) LastVerifiedBatch(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "lastVerifiedBatch") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. -// -// Solidity: function lastVerifiedBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencySession) LastVerifiedBatch() (uint64, error) { - return _Proofofefficiency.Contract.LastVerifiedBatch(&_Proofofefficiency.CallOpts) -} - -// LastVerifiedBatch is a free data retrieval call binding the contract method 0x7fcb3653. -// -// Solidity: function lastVerifiedBatch() view returns(uint64) -func (_Proofofefficiency *ProofofefficiencyCallerSession) LastVerifiedBatch() (uint64, error) { - return _Proofofefficiency.Contract.LastVerifiedBatch(&_Proofofefficiency.CallOpts) -} - -// Matic is a free data retrieval call binding the contract method 0xb6b0b097. -// -// Solidity: function matic() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCaller) Matic(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "matic") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Matic is a free data retrieval call binding the contract method 0xb6b0b097. -// -// Solidity: function matic() view returns(address) -func (_Proofofefficiency *ProofofefficiencySession) Matic() (common.Address, error) { - return _Proofofefficiency.Contract.Matic(&_Proofofefficiency.CallOpts) -} - -// Matic is a free data retrieval call binding the contract method 0xb6b0b097. -// -// Solidity: function matic() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCallerSession) Matic() (common.Address, error) { - return _Proofofefficiency.Contract.Matic(&_Proofofefficiency.CallOpts) -} - -// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. -// -// Solidity: function networkName() view returns(string) -func (_Proofofefficiency *ProofofefficiencyCaller) NetworkName(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "networkName") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. -// -// Solidity: function networkName() view returns(string) -func (_Proofofefficiency *ProofofefficiencySession) NetworkName() (string, error) { - return _Proofofefficiency.Contract.NetworkName(&_Proofofefficiency.CallOpts) -} - -// NetworkName is a free data retrieval call binding the contract method 0x107bf28c. -// -// Solidity: function networkName() view returns(string) -func (_Proofofefficiency *ProofofefficiencyCallerSession) NetworkName() (string, error) { - return _Proofofefficiency.Contract.NetworkName(&_Proofofefficiency.CallOpts) -} - -// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. -// -// Solidity: function rollupVerifier() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCaller) RollupVerifier(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "rollupVerifier") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. -// -// Solidity: function rollupVerifier() view returns(address) -func (_Proofofefficiency *ProofofefficiencySession) RollupVerifier() (common.Address, error) { - return _Proofofefficiency.Contract.RollupVerifier(&_Proofofefficiency.CallOpts) -} - -// RollupVerifier is a free data retrieval call binding the contract method 0xe8bf92ed. -// -// Solidity: function rollupVerifier() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCallerSession) RollupVerifier() (common.Address, error) { - return _Proofofefficiency.Contract.RollupVerifier(&_Proofofefficiency.CallOpts) -} - -// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. -// -// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 batchHashData, uint64 timestamp, uint64 forceBatchNum) -func (_Proofofefficiency *ProofofefficiencyCaller) SequencedBatches(opts *bind.CallOpts, arg0 uint64) (struct { - BatchHashData [32]byte - Timestamp uint64 - ForceBatchNum uint64 -}, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "sequencedBatches", arg0) - - outstruct := new(struct { - BatchHashData [32]byte - Timestamp uint64 - ForceBatchNum uint64 - }) - if err != nil { - return *outstruct, err - } - - outstruct.BatchHashData = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - outstruct.Timestamp = *abi.ConvertType(out[1], new(uint64)).(*uint64) - outstruct.ForceBatchNum = *abi.ConvertType(out[2], new(uint64)).(*uint64) - - return *outstruct, err - -} - -// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. -// -// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 batchHashData, uint64 timestamp, uint64 forceBatchNum) -func (_Proofofefficiency *ProofofefficiencySession) SequencedBatches(arg0 uint64) (struct { - BatchHashData [32]byte - Timestamp uint64 - ForceBatchNum uint64 -}, error) { - return _Proofofefficiency.Contract.SequencedBatches(&_Proofofefficiency.CallOpts, arg0) -} - -// SequencedBatches is a free data retrieval call binding the contract method 0xb4d63f58. -// -// Solidity: function sequencedBatches(uint64 ) view returns(bytes32 batchHashData, uint64 timestamp, uint64 forceBatchNum) -func (_Proofofefficiency *ProofofefficiencyCallerSession) SequencedBatches(arg0 uint64) (struct { - BatchHashData [32]byte - Timestamp uint64 - ForceBatchNum uint64 -}, error) { - return _Proofofefficiency.Contract.SequencedBatches(&_Proofofefficiency.CallOpts, arg0) -} - -// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. -// -// Solidity: function trustedSequencer() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCaller) TrustedSequencer(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "trustedSequencer") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. -// -// Solidity: function trustedSequencer() view returns(address) -func (_Proofofefficiency *ProofofefficiencySession) TrustedSequencer() (common.Address, error) { - return _Proofofefficiency.Contract.TrustedSequencer(&_Proofofefficiency.CallOpts) -} - -// TrustedSequencer is a free data retrieval call binding the contract method 0xcfa8ed47. -// -// Solidity: function trustedSequencer() view returns(address) -func (_Proofofefficiency *ProofofefficiencyCallerSession) TrustedSequencer() (common.Address, error) { - return _Proofofefficiency.Contract.TrustedSequencer(&_Proofofefficiency.CallOpts) -} - -// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. -// -// Solidity: function trustedSequencerURL() view returns(string) -func (_Proofofefficiency *ProofofefficiencyCaller) TrustedSequencerURL(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _Proofofefficiency.contract.Call(opts, &out, "trustedSequencerURL") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. -// -// Solidity: function trustedSequencerURL() view returns(string) -func (_Proofofefficiency *ProofofefficiencySession) TrustedSequencerURL() (string, error) { - return _Proofofefficiency.Contract.TrustedSequencerURL(&_Proofofefficiency.CallOpts) -} - -// TrustedSequencerURL is a free data retrieval call binding the contract method 0x542028d5. -// -// Solidity: function trustedSequencerURL() view returns(string) -func (_Proofofefficiency *ProofofefficiencyCallerSession) TrustedSequencerURL() (string, error) { - return _Proofofefficiency.Contract.TrustedSequencerURL(&_Proofofefficiency.CallOpts) -} - -// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. -// -// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) ForceBatch(opts *bind.TransactOpts, transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "forceBatch", transactions, maticAmount) -} - -// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. -// -// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() -func (_Proofofefficiency *ProofofefficiencySession) ForceBatch(transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { - return _Proofofefficiency.Contract.ForceBatch(&_Proofofefficiency.TransactOpts, transactions, maticAmount) -} - -// ForceBatch is a paid mutator transaction binding the contract method 0xeaeb077b. -// -// Solidity: function forceBatch(bytes transactions, uint256 maticAmount) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) ForceBatch(transactions []byte, maticAmount *big.Int) (*types.Transaction, error) { - return _Proofofefficiency.Contract.ForceBatch(&_Proofofefficiency.TransactOpts, transactions, maticAmount) -} - -// Initialize is a paid mutator transaction binding the contract method 0xd2fd1b31. -// -// Solidity: function initialize(address _globalExitRootManager, address _matic, address _rollupVerifier, bytes32 genesisRoot, address _trustedSequencer, bool _forceBatchAllowed, string _trustedSequencerURL, uint64 _chainID, string _networkName) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) Initialize(opts *bind.TransactOpts, _globalExitRootManager common.Address, _matic common.Address, _rollupVerifier common.Address, genesisRoot [32]byte, _trustedSequencer common.Address, _forceBatchAllowed bool, _trustedSequencerURL string, _chainID uint64, _networkName string) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "initialize", _globalExitRootManager, _matic, _rollupVerifier, genesisRoot, _trustedSequencer, _forceBatchAllowed, _trustedSequencerURL, _chainID, _networkName) -} - -// Initialize is a paid mutator transaction binding the contract method 0xd2fd1b31. -// -// Solidity: function initialize(address _globalExitRootManager, address _matic, address _rollupVerifier, bytes32 genesisRoot, address _trustedSequencer, bool _forceBatchAllowed, string _trustedSequencerURL, uint64 _chainID, string _networkName) returns() -func (_Proofofefficiency *ProofofefficiencySession) Initialize(_globalExitRootManager common.Address, _matic common.Address, _rollupVerifier common.Address, genesisRoot [32]byte, _trustedSequencer common.Address, _forceBatchAllowed bool, _trustedSequencerURL string, _chainID uint64, _networkName string) (*types.Transaction, error) { - return _Proofofefficiency.Contract.Initialize(&_Proofofefficiency.TransactOpts, _globalExitRootManager, _matic, _rollupVerifier, genesisRoot, _trustedSequencer, _forceBatchAllowed, _trustedSequencerURL, _chainID, _networkName) -} - -// Initialize is a paid mutator transaction binding the contract method 0xd2fd1b31. -// -// Solidity: function initialize(address _globalExitRootManager, address _matic, address _rollupVerifier, bytes32 genesisRoot, address _trustedSequencer, bool _forceBatchAllowed, string _trustedSequencerURL, uint64 _chainID, string _networkName) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) Initialize(_globalExitRootManager common.Address, _matic common.Address, _rollupVerifier common.Address, genesisRoot [32]byte, _trustedSequencer common.Address, _forceBatchAllowed bool, _trustedSequencerURL string, _chainID uint64, _networkName string) (*types.Transaction, error) { - return _Proofofefficiency.Contract.Initialize(&_Proofofefficiency.TransactOpts, _globalExitRootManager, _matic, _rollupVerifier, genesisRoot, _trustedSequencer, _forceBatchAllowed, _trustedSequencerURL, _chainID, _networkName) -} - -// SequenceBatches is a paid mutator transaction binding the contract method 0xf7d2cd7f. -// -// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64[])[] batches) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) SequenceBatches(opts *bind.TransactOpts, batches []ProofOfEfficiencyBatchData) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "sequenceBatches", batches) -} - -// SequenceBatches is a paid mutator transaction binding the contract method 0xf7d2cd7f. -// -// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64[])[] batches) returns() -func (_Proofofefficiency *ProofofefficiencySession) SequenceBatches(batches []ProofOfEfficiencyBatchData) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SequenceBatches(&_Proofofefficiency.TransactOpts, batches) -} - -// SequenceBatches is a paid mutator transaction binding the contract method 0xf7d2cd7f. -// -// Solidity: function sequenceBatches((bytes,bytes32,uint64,uint64[])[] batches) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) SequenceBatches(batches []ProofOfEfficiencyBatchData) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SequenceBatches(&_Proofofefficiency.TransactOpts, batches) -} - -// SequenceForceBatches is a paid mutator transaction binding the contract method 0xaa0f4418. -// -// Solidity: function sequenceForceBatches(uint64 numForcedBatches) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) SequenceForceBatches(opts *bind.TransactOpts, numForcedBatches uint64) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "sequenceForceBatches", numForcedBatches) -} - -// SequenceForceBatches is a paid mutator transaction binding the contract method 0xaa0f4418. -// -// Solidity: function sequenceForceBatches(uint64 numForcedBatches) returns() -func (_Proofofefficiency *ProofofefficiencySession) SequenceForceBatches(numForcedBatches uint64) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SequenceForceBatches(&_Proofofefficiency.TransactOpts, numForcedBatches) -} - -// SequenceForceBatches is a paid mutator transaction binding the contract method 0xaa0f4418. -// -// Solidity: function sequenceForceBatches(uint64 numForcedBatches) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) SequenceForceBatches(numForcedBatches uint64) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SequenceForceBatches(&_Proofofefficiency.TransactOpts, numForcedBatches) -} - -// SetForceBatchAllowed is a paid mutator transaction binding the contract method 0x8c4a0af7. -// -// Solidity: function setForceBatchAllowed(bool newForceBatchAllowed) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) SetForceBatchAllowed(opts *bind.TransactOpts, newForceBatchAllowed bool) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "setForceBatchAllowed", newForceBatchAllowed) -} - -// SetForceBatchAllowed is a paid mutator transaction binding the contract method 0x8c4a0af7. -// -// Solidity: function setForceBatchAllowed(bool newForceBatchAllowed) returns() -func (_Proofofefficiency *ProofofefficiencySession) SetForceBatchAllowed(newForceBatchAllowed bool) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetForceBatchAllowed(&_Proofofefficiency.TransactOpts, newForceBatchAllowed) -} - -// SetForceBatchAllowed is a paid mutator transaction binding the contract method 0x8c4a0af7. -// -// Solidity: function setForceBatchAllowed(bool newForceBatchAllowed) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) SetForceBatchAllowed(newForceBatchAllowed bool) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetForceBatchAllowed(&_Proofofefficiency.TransactOpts, newForceBatchAllowed) -} - -// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. -// -// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) SetTrustedSequencer(opts *bind.TransactOpts, newTrustedSequencer common.Address) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "setTrustedSequencer", newTrustedSequencer) -} - -// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. -// -// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() -func (_Proofofefficiency *ProofofefficiencySession) SetTrustedSequencer(newTrustedSequencer common.Address) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetTrustedSequencer(&_Proofofefficiency.TransactOpts, newTrustedSequencer) -} - -// SetTrustedSequencer is a paid mutator transaction binding the contract method 0x6ff512cc. -// -// Solidity: function setTrustedSequencer(address newTrustedSequencer) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) SetTrustedSequencer(newTrustedSequencer common.Address) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetTrustedSequencer(&_Proofofefficiency.TransactOpts, newTrustedSequencer) -} - -// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. -// -// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) SetTrustedSequencerURL(opts *bind.TransactOpts, newTrustedSequencerURL string) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "setTrustedSequencerURL", newTrustedSequencerURL) -} - -// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. -// -// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() -func (_Proofofefficiency *ProofofefficiencySession) SetTrustedSequencerURL(newTrustedSequencerURL string) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetTrustedSequencerURL(&_Proofofefficiency.TransactOpts, newTrustedSequencerURL) -} - -// SetTrustedSequencerURL is a paid mutator transaction binding the contract method 0xc89e42df. -// -// Solidity: function setTrustedSequencerURL(string newTrustedSequencerURL) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) SetTrustedSequencerURL(newTrustedSequencerURL string) (*types.Transaction, error) { - return _Proofofefficiency.Contract.SetTrustedSequencerURL(&_Proofofefficiency.TransactOpts, newTrustedSequencerURL) -} - -// VerifyBatch is a paid mutator transaction binding the contract method 0x95297e24. -// -// Solidity: function verifyBatch(bytes32 newLocalExitRoot, bytes32 newStateRoot, uint64 numBatch, uint256[2] proofA, uint256[2][2] proofB, uint256[2] proofC) returns() -func (_Proofofefficiency *ProofofefficiencyTransactor) VerifyBatch(opts *bind.TransactOpts, newLocalExitRoot [32]byte, newStateRoot [32]byte, numBatch uint64, proofA [2]*big.Int, proofB [2][2]*big.Int, proofC [2]*big.Int) (*types.Transaction, error) { - return _Proofofefficiency.contract.Transact(opts, "verifyBatch", newLocalExitRoot, newStateRoot, numBatch, proofA, proofB, proofC) -} - -// VerifyBatch is a paid mutator transaction binding the contract method 0x95297e24. -// -// Solidity: function verifyBatch(bytes32 newLocalExitRoot, bytes32 newStateRoot, uint64 numBatch, uint256[2] proofA, uint256[2][2] proofB, uint256[2] proofC) returns() -func (_Proofofefficiency *ProofofefficiencySession) VerifyBatch(newLocalExitRoot [32]byte, newStateRoot [32]byte, numBatch uint64, proofA [2]*big.Int, proofB [2][2]*big.Int, proofC [2]*big.Int) (*types.Transaction, error) { - return _Proofofefficiency.Contract.VerifyBatch(&_Proofofefficiency.TransactOpts, newLocalExitRoot, newStateRoot, numBatch, proofA, proofB, proofC) -} - -// VerifyBatch is a paid mutator transaction binding the contract method 0x95297e24. -// -// Solidity: function verifyBatch(bytes32 newLocalExitRoot, bytes32 newStateRoot, uint64 numBatch, uint256[2] proofA, uint256[2][2] proofB, uint256[2] proofC) returns() -func (_Proofofefficiency *ProofofefficiencyTransactorSession) VerifyBatch(newLocalExitRoot [32]byte, newStateRoot [32]byte, numBatch uint64, proofA [2]*big.Int, proofB [2][2]*big.Int, proofC [2]*big.Int) (*types.Transaction, error) { - return _Proofofefficiency.Contract.VerifyBatch(&_Proofofefficiency.TransactOpts, newLocalExitRoot, newStateRoot, numBatch, proofA, proofB, proofC) -} - -// ProofofefficiencyForceBatchIterator is returned from FilterForceBatch and is used to iterate over the raw logs and unpacked data for ForceBatch events raised by the Proofofefficiency contract. -type ProofofefficiencyForceBatchIterator struct { - Event *ProofofefficiencyForceBatch // 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 *ProofofefficiencyForceBatchIterator) 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(ProofofefficiencyForceBatch) - 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(ProofofefficiencyForceBatch) - 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 *ProofofefficiencyForceBatchIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencyForceBatchIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencyForceBatch represents a ForceBatch event raised by the Proofofefficiency contract. -type ProofofefficiencyForceBatch struct { - ForceBatchNum uint64 - LastGlobalExitRoot [32]byte - Sequencer common.Address - Transactions []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterForceBatch is a free log retrieval operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. -// -// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterForceBatch(opts *bind.FilterOpts, forceBatchNum []uint64) (*ProofofefficiencyForceBatchIterator, error) { - - var forceBatchNumRule []interface{} - for _, forceBatchNumItem := range forceBatchNum { - forceBatchNumRule = append(forceBatchNumRule, forceBatchNumItem) - } - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "ForceBatch", forceBatchNumRule) - if err != nil { - return nil, err - } - return &ProofofefficiencyForceBatchIterator{contract: _Proofofefficiency.contract, event: "ForceBatch", logs: logs, sub: sub}, nil -} - -// WatchForceBatch is a free log subscription operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. -// -// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchForceBatch(opts *bind.WatchOpts, sink chan<- *ProofofefficiencyForceBatch, forceBatchNum []uint64) (event.Subscription, error) { - - var forceBatchNumRule []interface{} - for _, forceBatchNumItem := range forceBatchNum { - forceBatchNumRule = append(forceBatchNumRule, forceBatchNumItem) - } - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "ForceBatch", forceBatchNumRule) - 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(ProofofefficiencyForceBatch) - if err := _Proofofefficiency.contract.UnpackLog(event, "ForceBatch", 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 -} - -// ParseForceBatch is a log parse operation binding the contract event 0xf94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931. -// -// Solidity: event ForceBatch(uint64 indexed forceBatchNum, bytes32 lastGlobalExitRoot, address sequencer, bytes transactions) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseForceBatch(log types.Log) (*ProofofefficiencyForceBatch, error) { - event := new(ProofofefficiencyForceBatch) - if err := _Proofofefficiency.contract.UnpackLog(event, "ForceBatch", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencyInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the Proofofefficiency contract. -type ProofofefficiencyInitializedIterator struct { - Event *ProofofefficiencyInitialized // 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 *ProofofefficiencyInitializedIterator) 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(ProofofefficiencyInitialized) - 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(ProofofefficiencyInitialized) - 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 *ProofofefficiencyInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencyInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencyInitialized represents a Initialized event raised by the Proofofefficiency contract. -type ProofofefficiencyInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterInitialized(opts *bind.FilterOpts) (*ProofofefficiencyInitializedIterator, error) { - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &ProofofefficiencyInitializedIterator{contract: _Proofofefficiency.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *ProofofefficiencyInitialized) (event.Subscription, error) { - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "Initialized") - 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(ProofofefficiencyInitialized) - if err := _Proofofefficiency.contract.UnpackLog(event, "Initialized", 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 -} - -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseInitialized(log types.Log) (*ProofofefficiencyInitialized, error) { - event := new(ProofofefficiencyInitialized) - if err := _Proofofefficiency.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencySequenceBatchesIterator is returned from FilterSequenceBatches and is used to iterate over the raw logs and unpacked data for SequenceBatches events raised by the Proofofefficiency contract. -type ProofofefficiencySequenceBatchesIterator struct { - Event *ProofofefficiencySequenceBatches // 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 *ProofofefficiencySequenceBatchesIterator) 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(ProofofefficiencySequenceBatches) - 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(ProofofefficiencySequenceBatches) - 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 *ProofofefficiencySequenceBatchesIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencySequenceBatchesIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencySequenceBatches represents a SequenceBatches event raised by the Proofofefficiency contract. -type ProofofefficiencySequenceBatches struct { - NumBatch uint64 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSequenceBatches is a free log retrieval operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. -// -// Solidity: event SequenceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterSequenceBatches(opts *bind.FilterOpts, numBatch []uint64) (*ProofofefficiencySequenceBatchesIterator, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "SequenceBatches", numBatchRule) - if err != nil { - return nil, err - } - return &ProofofefficiencySequenceBatchesIterator{contract: _Proofofefficiency.contract, event: "SequenceBatches", logs: logs, sub: sub}, nil -} - -// WatchSequenceBatches is a free log subscription operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. -// -// Solidity: event SequenceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchSequenceBatches(opts *bind.WatchOpts, sink chan<- *ProofofefficiencySequenceBatches, numBatch []uint64) (event.Subscription, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "SequenceBatches", numBatchRule) - 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(ProofofefficiencySequenceBatches) - if err := _Proofofefficiency.contract.UnpackLog(event, "SequenceBatches", 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 -} - -// ParseSequenceBatches is a log parse operation binding the contract event 0x303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce. -// -// Solidity: event SequenceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseSequenceBatches(log types.Log) (*ProofofefficiencySequenceBatches, error) { - event := new(ProofofefficiencySequenceBatches) - if err := _Proofofefficiency.contract.UnpackLog(event, "SequenceBatches", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencySequenceForceBatchesIterator is returned from FilterSequenceForceBatches and is used to iterate over the raw logs and unpacked data for SequenceForceBatches events raised by the Proofofefficiency contract. -type ProofofefficiencySequenceForceBatchesIterator struct { - Event *ProofofefficiencySequenceForceBatches // 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 *ProofofefficiencySequenceForceBatchesIterator) 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(ProofofefficiencySequenceForceBatches) - 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(ProofofefficiencySequenceForceBatches) - 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 *ProofofefficiencySequenceForceBatchesIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencySequenceForceBatchesIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencySequenceForceBatches represents a SequenceForceBatches event raised by the Proofofefficiency contract. -type ProofofefficiencySequenceForceBatches struct { - NumBatch uint64 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSequenceForceBatches is a free log retrieval operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. -// -// Solidity: event SequenceForceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterSequenceForceBatches(opts *bind.FilterOpts, numBatch []uint64) (*ProofofefficiencySequenceForceBatchesIterator, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "SequenceForceBatches", numBatchRule) - if err != nil { - return nil, err - } - return &ProofofefficiencySequenceForceBatchesIterator{contract: _Proofofefficiency.contract, event: "SequenceForceBatches", logs: logs, sub: sub}, nil -} - -// WatchSequenceForceBatches is a free log subscription operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. -// -// Solidity: event SequenceForceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchSequenceForceBatches(opts *bind.WatchOpts, sink chan<- *ProofofefficiencySequenceForceBatches, numBatch []uint64) (event.Subscription, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "SequenceForceBatches", numBatchRule) - 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(ProofofefficiencySequenceForceBatches) - if err := _Proofofefficiency.contract.UnpackLog(event, "SequenceForceBatches", 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 -} - -// ParseSequenceForceBatches is a log parse operation binding the contract event 0x648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4. -// -// Solidity: event SequenceForceBatches(uint64 indexed numBatch) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseSequenceForceBatches(log types.Log) (*ProofofefficiencySequenceForceBatches, error) { - event := new(ProofofefficiencySequenceForceBatches) - if err := _Proofofefficiency.contract.UnpackLog(event, "SequenceForceBatches", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencySetForceBatchAllowedIterator is returned from FilterSetForceBatchAllowed and is used to iterate over the raw logs and unpacked data for SetForceBatchAllowed events raised by the Proofofefficiency contract. -type ProofofefficiencySetForceBatchAllowedIterator struct { - Event *ProofofefficiencySetForceBatchAllowed // 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 *ProofofefficiencySetForceBatchAllowedIterator) 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(ProofofefficiencySetForceBatchAllowed) - 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(ProofofefficiencySetForceBatchAllowed) - 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 *ProofofefficiencySetForceBatchAllowedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencySetForceBatchAllowedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencySetForceBatchAllowed represents a SetForceBatchAllowed event raised by the Proofofefficiency contract. -type ProofofefficiencySetForceBatchAllowed struct { - NewForceBatchAllowed bool - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSetForceBatchAllowed is a free log retrieval operation binding the contract event 0xbacda50a4a8575be1d91a7ebe29ee45056f3a94f12a2281eb6b43afa33bcefe6. -// -// Solidity: event SetForceBatchAllowed(bool newForceBatchAllowed) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterSetForceBatchAllowed(opts *bind.FilterOpts) (*ProofofefficiencySetForceBatchAllowedIterator, error) { - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "SetForceBatchAllowed") - if err != nil { - return nil, err - } - return &ProofofefficiencySetForceBatchAllowedIterator{contract: _Proofofefficiency.contract, event: "SetForceBatchAllowed", logs: logs, sub: sub}, nil -} - -// WatchSetForceBatchAllowed is a free log subscription operation binding the contract event 0xbacda50a4a8575be1d91a7ebe29ee45056f3a94f12a2281eb6b43afa33bcefe6. -// -// Solidity: event SetForceBatchAllowed(bool newForceBatchAllowed) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchSetForceBatchAllowed(opts *bind.WatchOpts, sink chan<- *ProofofefficiencySetForceBatchAllowed) (event.Subscription, error) { - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "SetForceBatchAllowed") - 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(ProofofefficiencySetForceBatchAllowed) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetForceBatchAllowed", 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 -} - -// ParseSetForceBatchAllowed is a log parse operation binding the contract event 0xbacda50a4a8575be1d91a7ebe29ee45056f3a94f12a2281eb6b43afa33bcefe6. -// -// Solidity: event SetForceBatchAllowed(bool newForceBatchAllowed) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseSetForceBatchAllowed(log types.Log) (*ProofofefficiencySetForceBatchAllowed, error) { - event := new(ProofofefficiencySetForceBatchAllowed) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetForceBatchAllowed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencySetTrustedSequencerIterator is returned from FilterSetTrustedSequencer and is used to iterate over the raw logs and unpacked data for SetTrustedSequencer events raised by the Proofofefficiency contract. -type ProofofefficiencySetTrustedSequencerIterator struct { - Event *ProofofefficiencySetTrustedSequencer // 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 *ProofofefficiencySetTrustedSequencerIterator) 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(ProofofefficiencySetTrustedSequencer) - 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(ProofofefficiencySetTrustedSequencer) - 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 *ProofofefficiencySetTrustedSequencerIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencySetTrustedSequencerIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencySetTrustedSequencer represents a SetTrustedSequencer event raised by the Proofofefficiency contract. -type ProofofefficiencySetTrustedSequencer struct { - NewTrustedSequencer common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSetTrustedSequencer is a free log retrieval operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. -// -// Solidity: event SetTrustedSequencer(address newTrustedSequencer) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterSetTrustedSequencer(opts *bind.FilterOpts) (*ProofofefficiencySetTrustedSequencerIterator, error) { - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "SetTrustedSequencer") - if err != nil { - return nil, err - } - return &ProofofefficiencySetTrustedSequencerIterator{contract: _Proofofefficiency.contract, event: "SetTrustedSequencer", logs: logs, sub: sub}, nil -} - -// WatchSetTrustedSequencer is a free log subscription operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. -// -// Solidity: event SetTrustedSequencer(address newTrustedSequencer) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchSetTrustedSequencer(opts *bind.WatchOpts, sink chan<- *ProofofefficiencySetTrustedSequencer) (event.Subscription, error) { - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "SetTrustedSequencer") - 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(ProofofefficiencySetTrustedSequencer) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetTrustedSequencer", 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 -} - -// ParseSetTrustedSequencer is a log parse operation binding the contract event 0xf54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0. -// -// Solidity: event SetTrustedSequencer(address newTrustedSequencer) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseSetTrustedSequencer(log types.Log) (*ProofofefficiencySetTrustedSequencer, error) { - event := new(ProofofefficiencySetTrustedSequencer) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetTrustedSequencer", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencySetTrustedSequencerURLIterator is returned from FilterSetTrustedSequencerURL and is used to iterate over the raw logs and unpacked data for SetTrustedSequencerURL events raised by the Proofofefficiency contract. -type ProofofefficiencySetTrustedSequencerURLIterator struct { - Event *ProofofefficiencySetTrustedSequencerURL // 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 *ProofofefficiencySetTrustedSequencerURLIterator) 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(ProofofefficiencySetTrustedSequencerURL) - 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(ProofofefficiencySetTrustedSequencerURL) - 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 *ProofofefficiencySetTrustedSequencerURLIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencySetTrustedSequencerURLIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencySetTrustedSequencerURL represents a SetTrustedSequencerURL event raised by the Proofofefficiency contract. -type ProofofefficiencySetTrustedSequencerURL struct { - NewTrustedSequencerURL string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSetTrustedSequencerURL is a free log retrieval operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. -// -// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterSetTrustedSequencerURL(opts *bind.FilterOpts) (*ProofofefficiencySetTrustedSequencerURLIterator, error) { - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "SetTrustedSequencerURL") - if err != nil { - return nil, err - } - return &ProofofefficiencySetTrustedSequencerURLIterator{contract: _Proofofefficiency.contract, event: "SetTrustedSequencerURL", logs: logs, sub: sub}, nil -} - -// WatchSetTrustedSequencerURL is a free log subscription operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. -// -// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchSetTrustedSequencerURL(opts *bind.WatchOpts, sink chan<- *ProofofefficiencySetTrustedSequencerURL) (event.Subscription, error) { - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "SetTrustedSequencerURL") - 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(ProofofefficiencySetTrustedSequencerURL) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetTrustedSequencerURL", 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 -} - -// ParseSetTrustedSequencerURL is a log parse operation binding the contract event 0x6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20. -// -// Solidity: event SetTrustedSequencerURL(string newTrustedSequencerURL) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseSetTrustedSequencerURL(log types.Log) (*ProofofefficiencySetTrustedSequencerURL, error) { - event := new(ProofofefficiencySetTrustedSequencerURL) - if err := _Proofofefficiency.contract.UnpackLog(event, "SetTrustedSequencerURL", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// ProofofefficiencyVerifyBatchIterator is returned from FilterVerifyBatch and is used to iterate over the raw logs and unpacked data for VerifyBatch events raised by the Proofofefficiency contract. -type ProofofefficiencyVerifyBatchIterator struct { - Event *ProofofefficiencyVerifyBatch // 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 *ProofofefficiencyVerifyBatchIterator) 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(ProofofefficiencyVerifyBatch) - 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(ProofofefficiencyVerifyBatch) - 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 *ProofofefficiencyVerifyBatchIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ProofofefficiencyVerifyBatchIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ProofofefficiencyVerifyBatch represents a VerifyBatch event raised by the Proofofefficiency contract. -type ProofofefficiencyVerifyBatch struct { - NumBatch uint64 - Aggregator common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterVerifyBatch is a free log retrieval operation binding the contract event 0x2cdf1508085a46c7241a7d78c5a1ec3d9246d1ab95e1c2a33676d29e17d42223. -// -// Solidity: event VerifyBatch(uint64 indexed numBatch, address indexed aggregator) -func (_Proofofefficiency *ProofofefficiencyFilterer) FilterVerifyBatch(opts *bind.FilterOpts, numBatch []uint64, aggregator []common.Address) (*ProofofefficiencyVerifyBatchIterator, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - var aggregatorRule []interface{} - for _, aggregatorItem := range aggregator { - aggregatorRule = append(aggregatorRule, aggregatorItem) - } - - logs, sub, err := _Proofofefficiency.contract.FilterLogs(opts, "VerifyBatch", numBatchRule, aggregatorRule) - if err != nil { - return nil, err - } - return &ProofofefficiencyVerifyBatchIterator{contract: _Proofofefficiency.contract, event: "VerifyBatch", logs: logs, sub: sub}, nil -} - -// WatchVerifyBatch is a free log subscription operation binding the contract event 0x2cdf1508085a46c7241a7d78c5a1ec3d9246d1ab95e1c2a33676d29e17d42223. -// -// Solidity: event VerifyBatch(uint64 indexed numBatch, address indexed aggregator) -func (_Proofofefficiency *ProofofefficiencyFilterer) WatchVerifyBatch(opts *bind.WatchOpts, sink chan<- *ProofofefficiencyVerifyBatch, numBatch []uint64, aggregator []common.Address) (event.Subscription, error) { - - var numBatchRule []interface{} - for _, numBatchItem := range numBatch { - numBatchRule = append(numBatchRule, numBatchItem) - } - var aggregatorRule []interface{} - for _, aggregatorItem := range aggregator { - aggregatorRule = append(aggregatorRule, aggregatorItem) - } - - logs, sub, err := _Proofofefficiency.contract.WatchLogs(opts, "VerifyBatch", numBatchRule, aggregatorRule) - 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(ProofofefficiencyVerifyBatch) - if err := _Proofofefficiency.contract.UnpackLog(event, "VerifyBatch", 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 -} - -// ParseVerifyBatch is a log parse operation binding the contract event 0x2cdf1508085a46c7241a7d78c5a1ec3d9246d1ab95e1c2a33676d29e17d42223. -// -// Solidity: event VerifyBatch(uint64 indexed numBatch, address indexed aggregator) -func (_Proofofefficiency *ProofofefficiencyFilterer) ParseVerifyBatch(log types.Log) (*ProofofefficiencyVerifyBatch, error) { - event := new(ProofofefficiencyVerifyBatch) - if err := _Proofofefficiency.contract.UnpackLog(event, "VerifyBatch", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/etherman/smartcontracts/script.sh b/etherman/smartcontracts/script.sh index e5c79b4108..4e4b117fe2 100755 --- a/etherman/smartcontracts/script.sh +++ b/etherman/smartcontracts/script.sh @@ -8,8 +8,8 @@ gen() { abigen --bin bin/${package}.bin --abi abi/${package}.abi --pkg=${package} --out=${package}/${package}.go } -gen proofofefficiency -gen bridge +gen polygonzkevm +gen polygonzkevmbridge gen matic -gen globalexitrootmanager +gen polygonzkevmglobalexitroot gen mockverifier \ No newline at end of file diff --git a/etherman/types.go b/etherman/types.go index 307f78152e..9e07a2fbc8 100644 --- a/etherman/types.go +++ b/etherman/types.go @@ -1,10 +1,9 @@ package etherman import ( - "math/big" "time" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" "github.com/ethereum/go-ethereum/common" ) @@ -17,25 +16,27 @@ type Block struct { ForcedBatches []ForcedBatch SequencedBatches [][]SequencedBatch VerifiedBatches []VerifiedBatch - SequencedForceBatches []SequencedForceBatch + SequencedForceBatches [][]SequencedForceBatch + ForkIDs []ForkID ReceivedAt time.Time } // GlobalExitRoot struct type GlobalExitRoot struct { - BlockNumber uint64 - GlobalExitRootNum *big.Int - MainnetExitRoot common.Hash - RollupExitRoot common.Hash - GlobalExitRoot common.Hash + BlockNumber uint64 + MainnetExitRoot common.Hash + RollupExitRoot common.Hash + GlobalExitRoot common.Hash } // SequencedBatch represents virtual batch type SequencedBatch struct { - BatchNumber uint64 - Coinbase common.Address - TxHash common.Hash - proofofefficiency.ProofOfEfficiencyBatchData + BatchNumber uint64 + SequencerAddr common.Address + TxHash common.Hash + Nonce uint64 + Coinbase common.Address + polygonzkevm.PolygonZkEVMBatchData } // ForcedBatch represents a ForcedBatch @@ -53,13 +54,23 @@ type VerifiedBatch struct { BlockNumber uint64 BatchNumber uint64 Aggregator common.Address + StateRoot common.Hash TxHash common.Hash } // SequencedForceBatch is a sturct to track the ForceSequencedBatches event. type SequencedForceBatch struct { - LastBatchSequenced uint64 - ForceBatchNumber uint64 - Coinbase common.Address - TxHash common.Hash + BatchNumber uint64 + Coinbase common.Address + TxHash common.Hash + Timestamp time.Time + Nonce uint64 + polygonzkevm.PolygonZkEVMForcedBatchData +} + +// ForkID is a sturct to track the ForkID event. +type ForkID struct { + BatchNumber uint64 + ForkID uint64 + Version string } diff --git a/etherman/types/finalproofinputs.go b/etherman/types/finalproofinputs.go new file mode 100644 index 0000000000..f5686691b4 --- /dev/null +++ b/etherman/types/finalproofinputs.go @@ -0,0 +1,10 @@ +package types + +import "github.com/0xPolygonHermez/zkevm-node/aggregator/pb" + +// FinalProofInputs struct +type FinalProofInputs struct { + FinalProof *pb.FinalProof + NewLocalExitRoot []byte + NewStateRoot []byte +} diff --git a/etherman/types/sequence.go b/etherman/types/sequence.go index bfc298608b..c79d58c329 100644 --- a/etherman/types/sequence.go +++ b/etherman/types/sequence.go @@ -4,15 +4,18 @@ import ( "reflect" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" ) // Sequence represents an operation sent to the PoE smart contract to be // processed. type Sequence struct { - GlobalExitRoot, StateRoot, LocalExitRoot common.Hash - Timestamp int64 - Txs []types.Transaction + GlobalExitRoot, StateRoot, LocalExitRoot common.Hash // + AccInputHash common.Hash // 1024 + Timestamp int64 //64 + BatchL2Data []byte + IsSequenceTooBig bool // 8 + BatchNumber uint64 // 64 + ForcedBatchTimestamp int64 // 64 } // IsEmpty checks is sequence struct is empty diff --git a/ethtxmanager/config.go b/ethtxmanager/config.go index cb68c0d159..3bf486bc04 100644 --- a/ethtxmanager/config.go +++ b/ethtxmanager/config.go @@ -4,19 +4,15 @@ import "github.com/0xPolygonHermez/zkevm-node/config/types" // Config is configuration for ethereum transaction manager type Config struct { - // MaxSendBatchTxRetries amount of how many tries for sending sendBatch tx to the ethereum - MaxSendBatchTxRetries uint32 `mapstructure:"MaxSendBatchTxRetries"` - // FrequencyForResendingFailedSendBatches frequency of the resending batches - FrequencyForResendingFailedSendBatches types.Duration `mapstructure:"FrequencyForResendingFailedSendBatches"` - - // MaxVerifyBatchTxRetries amount of how many tries for sending verifyBatch tx to the ethereum - MaxVerifyBatchTxRetries uint32 `mapstructure:"MaxVerifyBatchTxRetries"` - // FrequencyForResendingFailedVerifyBatch frequency of the resending verify batch function - FrequencyForResendingFailedVerifyBatch types.Duration `mapstructure:"FrequencyForResendingFailedVerifyBatch"` + // FrequencyToMonitorTxs frequency of the resending failed txs + FrequencyToMonitorTxs types.Duration `mapstructure:"FrequencyToMonitorTxs"` // WaitTxToBeMined time to wait after transaction was sent to the ethereum WaitTxToBeMined types.Duration `mapstructure:"WaitTxToBeMined"` - // PercentageToIncreaseGasPrice when tx is failed by timeout increase gas price by this percentage - PercentageToIncreaseGasPrice uint64 `mapstructure:"PercentageToIncreaseGasPrice"` - // PercentageToIncreaseGasLimit when tx is failed by timeout increase gas price by this percentage - PercentageToIncreaseGasLimit uint64 `mapstructure:"PercentageToIncreaseGasLimit"` + + // PrivateKeys defines all the key store files that are going + // to be read in order to provide the private keys to sign the L1 txs + PrivateKeys []types.KeystoreFileConfig `mapstructure:"PrivateKeys"` + + // ForcedGas is the amount of gas to be forced in case of gas estimation error + ForcedGas uint64 `mapstructure:"ForcedGas"` } diff --git a/ethtxmanager/ethtxmanager.go b/ethtxmanager/ethtxmanager.go index 258d6bfd44..e7099afddc 100644 --- a/ethtxmanager/ethtxmanager.go +++ b/ethtxmanager/ethtxmanager.go @@ -5,152 +5,639 @@ package ethtxmanager import ( + "context" + "errors" + "fmt" "math/big" - "strings" "time" - ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" ) -const oneHundred = 100 +const ( + failureIntervalInSeconds = 5 + // maxHistorySize = 10 +) + +var ( + // ErrNotFound when the object is not found + ErrNotFound = errors.New("not found") + // ErrAlreadyExists when the object already exists + ErrAlreadyExists = errors.New("already exists") + + // ErrExecutionReverted returned when trying to get the revert message + // but the call fails without revealing the revert reason + ErrExecutionReverted = errors.New("execution reverted") + + // gasOffsets for aggregator and sequencer + gasOffsets = map[string]uint64{ + "sequencer": 80000, //nolint:gomnd + "aggregator": 0, + } +) // Client for eth tx manager type Client struct { - cfg Config - ethMan etherman + ctx context.Context + cancel context.CancelFunc + + cfg Config + etherman ethermanInterface + storage storageInterface + state stateInterface } // New creates new eth tx manager -func New(cfg Config, ethMan etherman) *Client { - return &Client{ - cfg: cfg, - ethMan: ethMan, - } -} - -// SequenceBatches send sequences to the channel -func (c *Client) SequenceBatches(sequences []ethmanTypes.Sequence) { - var ( - attempts uint32 - gas uint64 - gasPrice *big.Int - nonce = big.NewInt(0) - ) - log.Info("sending sequence to L1") - for attempts < c.cfg.MaxSendBatchTxRetries { - var ( - tx *types.Transaction - err error - ) - if nonce.Uint64() > 0 { - tx, err = c.ethMan.SequenceBatches(sequences, gas, gasPrice, nonce) +func New(cfg Config, ethMan ethermanInterface, storage storageInterface, state stateInterface) *Client { + c := &Client{ + cfg: cfg, + etherman: ethMan, + storage: storage, + state: state, + } + + return c +} + +// Add a transaction to be sent and monitored +func (c *Client) Add(ctx context.Context, owner, id string, from common.Address, to *common.Address, value *big.Int, data []byte, dbTx pgx.Tx) error { + // get next nonce + nonce, err := c.etherman.CurrentNonce(ctx, from) + if err != nil { + err := fmt.Errorf("failed to get current nonce: %w", err) + log.Errorf(err.Error()) + return err + } + // get gas + gas, err := c.etherman.EstimateGas(ctx, from, to, value, data) + if err != nil { + err := fmt.Errorf("failed to estimate gas: %w, data: %v", err, common.Bytes2Hex(data)) + log.Error(err.Error()) + if c.cfg.ForcedGas > 0 { + gas = c.cfg.ForcedGas } else { - tx, err = c.ethMan.SequenceBatches(sequences, gas, gasPrice, nil) - } - for err != nil && attempts < c.cfg.MaxSendBatchTxRetries { - log.Errorf("failed to sequence batches, trying once again, retry #%d, gasLimit: %d, err: %w", - attempts, 0, err) - time.Sleep(c.cfg.FrequencyForResendingFailedSendBatches.Duration) - attempts++ - if nonce.Uint64() > 0 { - tx, err = c.ethMan.SequenceBatches(sequences, gas, gasPrice, nonce) - } else { - tx, err = c.ethMan.SequenceBatches(sequences, gas, gasPrice, nil) - } + return err } + } else { + offset := gasOffsets[owner] + gas += offset + log.Debugf("Applying gasOffset: %d. Final Gas: %d, Owner: %s", offset, gas, owner) + } + + // get gas price + gasPrice, err := c.etherman.SuggestedGasPrice(ctx) + if err != nil { + err := fmt.Errorf("failed to get suggested gas price: %w", err) + log.Errorf(err.Error()) + return err + } + + // create monitored tx + mTx := monitoredTx{ + owner: owner, id: id, from: from, to: to, + nonce: nonce, value: value, data: data, + gas: gas, gasPrice: gasPrice, + status: MonitoredTxStatusCreated, + } + + // add to storage + err = c.storage.Add(ctx, mTx, dbTx) + if err != nil { + err := fmt.Errorf("failed to add tx to get monitored: %w", err) + log.Errorf(err.Error()) + return err + } + + return nil +} + +// ResultsByStatus returns all the results for all the monitored txs related to the owner and matching the provided statuses +// if the statuses are empty, all the statuses are considered. +// +// the slice is returned is in order by created_at field ascending +func (c *Client) ResultsByStatus(ctx context.Context, owner string, statuses []MonitoredTxStatus, dbTx pgx.Tx) ([]MonitoredTxResult, error) { + mTxs, err := c.storage.GetByStatus(ctx, &owner, statuses, dbTx) + if err != nil { + return nil, err + } + + results := make([]MonitoredTxResult, 0, len(mTxs)) + + for _, mTx := range mTxs { + result, err := c.buildResult(ctx, mTx) if err != nil { - log.Fatalf("failed to sequence batches, maximum attempts exceeded, gasLimit: %d, err: %w", - 0, err) + return nil, err } - // Wait for tx to be mined - log.Infof("waiting for tx to be mined. Tx hash: %s, nonce: %d, gasPrice: %d", tx.Hash(), tx.Nonce(), tx.GasPrice().Int64()) - err = c.ethMan.WaitTxToBeMined(tx.Hash(), c.cfg.WaitTxToBeMined.Duration) + results = append(results, result) + } + + return results, nil +} + +// Result returns the current result of the transaction execution with all the details +func (c *Client) Result(ctx context.Context, owner, id string, dbTx pgx.Tx) (MonitoredTxResult, error) { + mTx, err := c.storage.Get(ctx, owner, id, dbTx) + if err != nil { + return MonitoredTxResult{}, err + } + + return c.buildResult(ctx, mTx) +} + +// SetStatusDone sets the status of a monitored tx to MonitoredStatusDone. +// this method is provided to the callers to decide when a monitored tx should be +// considered done, so they can start to ignore it when querying it by Status. +func (c *Client) setStatusDone(ctx context.Context, owner, id string, dbTx pgx.Tx) error { + mTx, err := c.storage.Get(ctx, owner, id, nil) + if err != nil { + return err + } + + mTx.status = MonitoredTxStatusDone + + return c.storage.Update(ctx, mTx, dbTx) +} + +func (c *Client) buildResult(ctx context.Context, mTx monitoredTx) (MonitoredTxResult, error) { + history := mTx.historyHashSlice() + txs := make(map[common.Hash]TxResult, len(history)) + + for _, txHash := range history { + tx, _, err := c.etherman.GetTx(ctx, txHash) + if !errors.Is(err, ethereum.NotFound) && err != nil { + return MonitoredTxResult{}, err + } + + receipt, err := c.etherman.GetTxReceipt(ctx, txHash) + if !errors.Is(err, ethereum.NotFound) && err != nil { + return MonitoredTxResult{}, err + } + + revertMessage, err := c.etherman.GetRevertMessage(ctx, tx) + if !errors.Is(err, ethereum.NotFound) && err != nil && err.Error() != ErrExecutionReverted.Error() { + return MonitoredTxResult{}, err + } + + txs[txHash] = TxResult{ + Tx: tx, + Receipt: receipt, + RevertMessage: revertMessage, + } + } + + result := MonitoredTxResult{ + ID: mTx.id, + Status: mTx.status, + Txs: txs, + } + + return result, nil +} + +// Start will start the tx management, reading txs from storage, +// send then to the blockchain and keep monitoring them until they +// get mined +func (c *Client) Start() { + // infinite loop to manage txs as they arrive + c.ctx, c.cancel = context.WithCancel(context.Background()) + + for { + select { + case <-c.ctx.Done(): + return + case <-time.After(c.cfg.FrequencyToMonitorTxs.Duration): + err := c.monitorTxs(context.Background()) + if err != nil { + c.logErrorAndWait("failed to monitor txs: %v", err) + } + } + } +} + +// Stop will stops the monitored tx management +func (c *Client) Stop() { + c.cancel() +} + +// Reorg updates all monitored txs from provided block number until the last one to +// Reorged status, allowing it to be reprocessed by the tx monitoring +func (c *Client) Reorg(ctx context.Context, fromBlockNumber uint64, dbTx pgx.Tx) error { + log.Infof("processing reorg from block: %v", fromBlockNumber) + mTxs, err := c.storage.GetByBlock(ctx, &fromBlockNumber, nil, dbTx) + if err != nil { + log.Errorf("failed to monitored tx by block: %v", err) + return err + } + log.Infof("updating %v monitored txs to reorged", len(mTxs)) + for _, mTx := range mTxs { + mTx.blockNumber = nil + mTx.status = MonitoredTxStatusReorged + + err = c.storage.Update(ctx, mTx, dbTx) if err != nil { - attempts++ - if strings.Contains(err.Error(), "out of gas") { - gas = increaseGasLimit(tx.Gas(), c.cfg.PercentageToIncreaseGasLimit) - log.Infof("out of gas with %d, retrying with %d", tx.Gas(), gas) + log.Errorf("failed to update monitored tx to reorg status: %v", err) + return err + } + log.Infof("monitored tx %v status updated to reorged", mTx.id) + } + log.Infof("reorg from block %v processed successfully", fromBlockNumber) + return nil +} + +// monitorTxs process all pending monitored tx +func (c *Client) monitorTxs(ctx context.Context) error { + statusesFilter := []MonitoredTxStatus{MonitoredTxStatusCreated, MonitoredTxStatusSent, MonitoredTxStatusReorged} + mTxs, err := c.storage.GetByStatus(ctx, nil, statusesFilter, nil) + if err != nil { + return fmt.Errorf("failed to get created monitored txs: %v", err) + } + + log.Infof("found %v monitored tx to process", len(mTxs)) + + for _, mTx := range mTxs { + mTx := mTx // force variable shadowing to avoid pointer conflicts + mTxLog := log.WithFields("monitoredTx", mTx.id) + mTxLog.Info("processing") + + // check if any of the txs in the history was mined + mined := false + var receipt *types.Receipt + hasFailedReceipts := false + allHistoryTxMined := true + for txHash := range mTx.history { + mined, receipt, err = c.etherman.CheckTxWasMined(ctx, txHash) + if err != nil { + mTxLog.Errorf("failed to check if tx %v was mined: %v", txHash.String(), err) continue - } else if strings.Contains(err.Error(), "timeout has been reached") { - nonce = new(big.Int).SetUint64(tx.Nonce()) - gasPrice = increaseGasPrice(tx.GasPrice(), c.cfg.PercentageToIncreaseGasPrice) - log.Infof("tx %s reached timeout, retrying with gas price = %d", tx.Hash(), gasPrice) + } + + // if the tx is not mined yet, check that not all the tx were mined and go to the next + if !mined { + allHistoryTxMined = false continue } - log.Fatalf("tx %s failed, err: %w", tx.Hash(), err) - } else { - log.Infof("sequence sent to L1 successfully. Tx hash: %s", tx.Hash()) - return + + // if the tx was mined successfully we can break the loop and proceed + if receipt.Status == types.ReceiptStatusSuccessful { + break + } + + // if the tx was mined but failed, we continue to consider it was not mined + // and store the failed receipt to be used to check if nonce needs to be reviewed + mined = false + hasFailedReceipts = true } - } -} -// VerifyBatch send VerifyBatch request to ethereum -func (c *Client) VerifyBatch(batchNum uint64, resGetProof *pb.GetProofResponse) { - var ( - attempts uint32 - gas uint64 - gasPrice *big.Int - nonce = big.NewInt(0) - ) - log.Infof("sending batch %d verification to L1", batchNum) - for attempts < c.cfg.MaxVerifyBatchTxRetries { - var ( - tx *types.Transaction - err error - ) - if nonce.Uint64() > 0 { - tx, err = c.ethMan.VerifyBatch(batchNum, resGetProof, gas, gasPrice, nonce) - } else { - tx, err = c.ethMan.VerifyBatch(batchNum, resGetProof, gas, gasPrice, nil) + // we need to check if we need to review the nonce carefully, to avoid sending + // duplicated data to the block chain. + // + // if we have failed receipts, this means at least one of the generated txs was mined + // so maybe the current nonce was already consumed, then we need to check if there are + // tx that were not mined yet, if so, we just need to wait, because maybe one of them + // will get mined successfully + // + // in case of all tx were mined and none of them were mined successfully, we need to + // review the nonce + if hasFailedReceipts && allHistoryTxMined { + mTxLog.Infof("nonce needs to be updated") + err := c.ReviewMonitoredTxNonce(ctx, &mTx) + if err != nil { + mTxLog.Errorf("failed to review monitored tx nonce: %v", err) + continue + } + err = c.storage.Update(ctx, mTx, nil) + if err != nil { + mTxLog.Errorf("failed to update monitored tx nonce change: %v", err) + continue + } } - for err != nil && attempts < c.cfg.MaxVerifyBatchTxRetries { - log.Errorf("failed to send batch verification, trying once again, retry #%d, gasLimit: %d, err: %w", attempts, 0, err) - time.Sleep(c.cfg.FrequencyForResendingFailedVerifyBatch.Duration) - if nonce.Uint64() > 0 { - tx, err = c.ethMan.VerifyBatch(batchNum, resGetProof, gas, gasPrice, nonce) + // if the history size reaches the max history size, this means something is really wrong with + // this Tx and we are not able to identify automatically, so we mark this as failed to let the + // caller know something is not right and needs to be review and to avoid to monitor this + // tx infinitely + // if len(mTx.history) == maxHistorySize { + // mTx.status = MonitoredTxStatusFailed + // mTxLog.Infof("marked as failed because reached the history size limit: %v", err) + // // update monitored tx changes into storage + // err = c.storage.Update(ctx, mTx, nil) + // if err != nil { + // mTxLog.Errorf("failed to update monitored tx when max history size limit reached: %v", err) + // continue + // } + // } + + var signedTx *types.Transaction + if !mined { + // if is a reorged, move to the next + if mTx.status == MonitoredTxStatusReorged { + continue + } + + // review tx and increase gas and gas price if needed + if mTx.status == MonitoredTxStatusSent { + err := c.ReviewMonitoredTx(ctx, &mTx) + if err != nil { + mTxLog.Errorf("failed to review monitored tx: %v", err) + continue + } + err = c.storage.Update(ctx, mTx, nil) + if err != nil { + mTxLog.Errorf("failed to update monitored tx review change: %v", err) + continue + } + } + + // rebuild transaction + tx := mTx.Tx() + mTxLog.Debugf("unsigned tx %v created", tx.Hash().String(), mTx.id) + + // sign tx + signedTx, err = c.etherman.SignTx(ctx, mTx.from, tx) + if err != nil { + mTxLog.Errorf("failed to sign tx %v created from monitored tx %v: %v", tx.Hash().String(), mTx.id, err) + continue + } + mTxLog.Debugf("signed tx %v created", signedTx.Hash().String()) + + // add tx to monitored tx history + err = mTx.AddHistory(signedTx) + if errors.Is(err, ErrAlreadyExists) { + mTxLog.Infof("signed tx already existed in the history") + } else if err != nil { + mTxLog.Errorf("failed to add signed tx to monitored tx %v history: %v", mTx.id, err) + continue } else { - tx, err = c.ethMan.VerifyBatch(batchNum, resGetProof, gas, gasPrice, nil) + // update monitored tx changes into storage + err = c.storage.Update(ctx, mTx, nil) + if err != nil { + mTxLog.Errorf("failed to update monitored tx: %v", err) + continue + } + mTxLog.Debugf("signed tx added to the monitored tx history") } - attempts++ - } - if err != nil { - log.Errorf("failed to send batch verification, maximum attempts exceeded, gasLimit: %d, err: %w", 0, err) - return + // check if the tx is already in the network, if not, send it + _, _, err = c.etherman.GetTx(ctx, signedTx.Hash()) + // if not found, send it tx to the network + if errors.Is(err, ethereum.NotFound) { + mTxLog.Debugf("signed tx not found in the network") + err := c.etherman.SendTx(ctx, signedTx) + if err != nil { + mTxLog.Errorf("failed to send tx %v to network: %v", signedTx.Hash().String(), err) + continue + } + mTxLog.Infof("signed tx sent to the network: %v", signedTx.Hash().String()) + if mTx.status == MonitoredTxStatusCreated { + // update tx status to sent + mTx.status = MonitoredTxStatusSent + mTxLog.Debugf("status changed to %v", string(mTx.status)) + // update monitored tx changes into storage + err = c.storage.Update(ctx, mTx, nil) + if err != nil { + mTxLog.Errorf("failed to update monitored tx changes: %v", err) + continue + } + } + } else { + mTxLog.Infof("signed tx already found in the network") + } + + log.Infof("waiting signedTx to be mined...") + + // wait tx to get mined + mined, err = c.etherman.WaitTxToBeMined(ctx, signedTx, c.cfg.WaitTxToBeMined.Duration) + if err != nil { + mTxLog.Errorf("failed to wait tx to be mined: %v", err) + continue + } + if !mined { + log.Infof("signedTx not mined yet and timeout has been reached") + continue + } + + // get tx receipt + receipt, err = c.etherman.GetTxReceipt(ctx, signedTx.Hash()) + if err != nil { + mTxLog.Errorf("failed to get tx receipt for tx %v: %v", signedTx.Hash().String(), err) + continue + } } - // Wait for tx to be mined - log.Infof("waiting for tx to be mined. Tx hash: %s, nonce: %d, gasPrice: %d", tx.Hash(), tx.Nonce(), tx.GasPrice().Int64()) - err = c.ethMan.WaitTxToBeMined(tx.Hash(), c.cfg.WaitTxToBeMined.Duration) - if err != nil { - if strings.Contains(err.Error(), "out of gas") { - gas = increaseGasLimit(tx.Gas(), c.cfg.PercentageToIncreaseGasLimit) - log.Infof("out of gas with %d, retrying with %d", tx.Gas(), gas) + + mTx.blockNumber = receipt.BlockNumber + + // if mined, check receipt and mark as Failed or Confirmed + if receipt.Status == types.ReceiptStatusSuccessful { + receiptBlockNum := receipt.BlockNumber.Uint64() + + // check block synced + block, err := c.state.GetLastBlock(ctx, nil) + if errors.Is(err, state.ErrStateNotSynchronized) { + mTxLog.Debugf("state not synchronized yet, waiting for L1 block %v to be synced", receiptBlockNum) continue - } else if strings.Contains(err.Error(), "timeout has been reached") { - nonce = new(big.Int).SetUint64(tx.Nonce()) - gasPrice = increaseGasPrice(tx.GasPrice(), c.cfg.PercentageToIncreaseGasPrice) - log.Infof("tx %s reached timeout, retrying with gas price = %d", tx.Hash(), gasPrice) + } else if err != nil { + mTxLog.Errorf("failed to check if L1 block %v is already synced: %v", receiptBlockNum, err) continue + } else if block.BlockNumber < receiptBlockNum { + mTxLog.Debugf("L1 block %v not synchronized yet, waiting for L1 block to be synced in order to confirm monitored tx", receiptBlockNum) + continue + } else { + mTxLog.Info("confirmed") + mTx.status = MonitoredTxStatusConfirmed } - log.Errorf("tx %s failed, err: %w", tx.Hash(), err) - return } else { - log.Infof("batch verification sent to L1 successfully. Tx hash: %s", tx.Hash()) - return + // if we should continue to monitor, we move to the next one and this will + // be reviewed in the next monitoring cycle + if c.shouldContinueToMonitorThisTx(ctx, receipt) { + continue + } + mTxLog.Info("failed") + // otherwise we understand this monitored tx has failed + mTx.status = MonitoredTxStatusFailed + } + + // update monitored tx changes into storage + err = c.storage.Update(ctx, mTx, nil) + if err != nil { + mTxLog.Errorf("failed to update monitored tx: %v", err) + continue } } + + return nil } -func increaseGasPrice(currentGasPrice *big.Int, percentageIncrease uint64) *big.Int { - gasPrice := big.NewInt(0).Mul(currentGasPrice, new(big.Int).SetUint64(uint64(oneHundred)+percentageIncrease)) - return gasPrice.Div(gasPrice, big.NewInt(oneHundred)) +// shouldContinueToMonitorThisTx checks the the tx receipt and decides if it should +// continue or not to monitor the monitored tx related to the tx from this receipt +func (c *Client) shouldContinueToMonitorThisTx(ctx context.Context, receipt *types.Receipt) bool { + // if the receipt has a is successful result, stop monitoring + if receipt.Status == types.ReceiptStatusSuccessful { + return false + } + + tx, _, err := c.etherman.GetTx(ctx, receipt.TxHash) + if err != nil { + log.Errorf("failed to get tx when monitored tx identified as failed, tx : %v", receipt.TxHash.String(), err) + return false + } + _, err = c.etherman.GetRevertMessage(ctx, tx) + if err != nil { + // if the error when getting the revert message is not identified, continue to monitor + if err.Error() == ErrExecutionReverted.Error() { + return true + } else { + log.Errorf("failed to get revert message for monitored tx identified as failed, tx %v: %v", receipt.TxHash.String(), err) + } + } + // if nothing weird was found, stop monitoring + return false +} + +// ReviewMonitoredTx checks if some field needs to be updated +// accordingly to the current information stored and the current +// state of the blockchain +func (c *Client) ReviewMonitoredTx(ctx context.Context, mTx *monitoredTx) error { + mTxLog := log.WithFields("monitoredTx", mTx.id) + mTxLog.Debug("reviewing") + // get gas + gas, err := c.etherman.EstimateGas(ctx, mTx.from, mTx.to, mTx.value, mTx.data) + if err != nil { + err := fmt.Errorf("failed to estimate gas: %w", err) + mTxLog.Errorf(err.Error()) + return err + } + + // check gas + if gas > mTx.gas { + mTxLog.Infof("monitored tx gas updated from %v to %v", mTx.gas, gas) + mTx.gas = gas + } + + // get gas price + gasPrice, err := c.etherman.SuggestedGasPrice(ctx) + if err != nil { + err := fmt.Errorf("failed to get suggested gas price: %w", err) + mTxLog.Errorf(err.Error()) + return err + } + + // check gas price + if gasPrice.Cmp(mTx.gasPrice) == 1 { + mTxLog.Infof("monitored tx gas price updated from %v to %v", mTx.gasPrice.String(), gasPrice.String()) + mTx.gasPrice = gasPrice + } + return nil +} + +// ReviewMonitoredTxNonce checks if the nonce needs to be updated accordingly to +// the current nonce of the sender account. +// +// IMPORTANT: Nonce is reviewed apart from the other fields because it is a very +// sensible information and can make duplicated data to be sent to the blockchain, +// causing possible side effects and wasting resources on taxes. +func (c *Client) ReviewMonitoredTxNonce(ctx context.Context, mTx *monitoredTx) error { + mTxLog := log.WithFields("monitoredTx", mTx.id) + mTxLog.Debug("reviewing nonce") + nonce, err := c.etherman.CurrentNonce(ctx, mTx.from) + if err != nil { + err := fmt.Errorf("failed to estimate gas: %w", err) + mTxLog.Errorf(err.Error()) + return err + } + + if nonce > mTx.nonce { + mTxLog.Infof("monitored tx nonce updated from %v to %v", mTx.nonce, nonce) + mTx.nonce = nonce + } + + return nil +} + +// logErrorAndWait used when an error is detected before trying again +func (c *Client) logErrorAndWait(msg string, err error) { + log.Errorf(msg, err) + time.Sleep(failureIntervalInSeconds * time.Second) } -func increaseGasLimit(currentGasLimit uint64, percentageIncrease uint64) uint64 { - return currentGasLimit * (oneHundred + percentageIncrease) / oneHundred +// ResultHandler used by the caller to handle results +// when processing monitored txs +type ResultHandler func(MonitoredTxResult, pgx.Tx) + +// ProcessPendingMonitoredTxs will check all monitored txs of this owner +// and wait until all of them are either confirmed or failed before continuing +// +// for the confirmed and failed ones, the resultHandler will be triggered +func (c *Client) ProcessPendingMonitoredTxs(ctx context.Context, owner string, resultHandler ResultHandler, dbTx pgx.Tx) { + statusesFilter := []MonitoredTxStatus{ + MonitoredTxStatusCreated, + MonitoredTxStatusSent, + MonitoredTxStatusFailed, + MonitoredTxStatusConfirmed, + MonitoredTxStatusReorged, + } + // keep running until there are pending monitored txs + for { + results, err := c.ResultsByStatus(ctx, owner, statusesFilter, dbTx) + if err != nil { + // if something goes wrong here, we log, wait a bit and keep it in the infinite loop to not unlock the caller. + log.Errorf("failed to get results by statuses from eth tx manager to monitored txs err: ", err) + time.Sleep(time.Second) + continue + } + + if len(results) == 0 { + // if there are not pending monitored txs, stop + return + } + + for _, result := range results { + resultLog := log.WithFields("owner", owner, "id", result.ID) + + // if the result is confirmed, we set it as done do stop looking into this monitored tx + if result.Status == MonitoredTxStatusConfirmed { + err := c.setStatusDone(ctx, owner, result.ID, dbTx) + if err != nil { + resultLog.Errorf("failed to set monitored tx as done, err: %v", err) + // if something goes wrong at this point, we skip this result and move to the next. + // this result is going to be handled again in the next cycle by the outer loop. + continue + } else { + resultLog.Info("monitored tx confirmed") + } + resultHandler(result, dbTx) + continue + } + + // if the result is failed, we need to go around it and rebuild a batch verification + if result.Status == MonitoredTxStatusFailed { + resultHandler(result, dbTx) + continue + } + + // if the result is either not confirmed or failed, it means we need to wait until it gets confirmed of failed. + for { + // wait before refreshing the result info + time.Sleep(time.Second) + + // refresh the result info + result, err := c.Result(ctx, owner, result.ID, dbTx) + if err != nil { + resultLog.Errorf("failed to get monitored tx result, err: %v", err) + continue + } + + // if the result status is confirmed or failed, breaks the wait loop + if result.Status == MonitoredTxStatusConfirmed || result.Status == MonitoredTxStatusFailed { + break + } + + resultLog.Infof("waiting for monitored tx to get confirmed, status: %v", result.Status.String()) + } + } + } } diff --git a/ethtxmanager/ethtxmanager_test.go b/ethtxmanager/ethtxmanager_test.go index 92132a8ce0..9d5b4e2b4b 100644 --- a/ethtxmanager/ethtxmanager_test.go +++ b/ethtxmanager/ethtxmanager_test.go @@ -1,18 +1,678 @@ package ethtxmanager import ( + "context" + "errors" "math/big" "testing" + "time" - "github.com/stretchr/testify/assert" + "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" ) -func TestIncreaseGasPrice(t *testing.T) { - actual := increaseGasPrice(big.NewInt(100), 1) - assert.Equal(t, big.NewInt(101), actual) +var defaultEthTxmanagerConfigForTests = Config{ + FrequencyToMonitorTxs: types.NewDuration(time.Millisecond), + WaitTxToBeMined: types.NewDuration(time.Second), } -func TestIncreaseGasLimit(t *testing.T) { - actual := increaseGasLimit(100, 1) - assert.Equal(t, uint64(101), actual) +func TestTxGetMined(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + etherman := newEthermanMock(t) + st := newStateMock(t) + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + ethTxManagerClient := New(defaultEthTxmanagerConfigForTests, etherman, storage, st) + + owner := "owner" + id := "unique_id" + from := common.HexToAddress("") + var to *common.Address + var value *big.Int + var data []byte = nil + + ctx := context.Background() + + currentNonce := uint64(1) + etherman. + On("CurrentNonce", ctx, from). + Return(currentNonce, nil). + Once() + + estimatedGas := uint64(1) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(estimatedGas, nil). + Once() + + suggestedGasPrice := big.NewInt(1) + etherman. + On("SuggestedGasPrice", ctx). + Return(suggestedGasPrice, nil). + Once() + + signedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: estimatedGas, + GasPrice: suggestedGasPrice, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(signedTx, nil). + Once() + + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(signedTx, false, nil). + Once() + + etherman. + On("SendTx", ctx, signedTx). + Return(nil). + Once() + + etherman. + On("WaitTxToBeMined", ctx, signedTx, mock.IsType(time.Second)). + Return(true, nil). + Once() + + blockNumber := big.NewInt(1) + + receipt := ðTypes.Receipt{ + BlockNumber: blockNumber, + Status: ethTypes.ReceiptStatusSuccessful, + } + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Return(receipt, nil). + Once() + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Run(func(args mock.Arguments) { ethTxManagerClient.Stop() }). // stops the management cycle to avoid problems with mocks + Return(receipt, nil). + Once() + + etherman. + On("GetRevertMessage", ctx, signedTx). + Return("", nil). + Once() + + block := &state.Block{ + BlockNumber: blockNumber.Uint64(), + } + st. + On("GetLastBlock", ctx, nil). + Return(block, nil). + Once() + + err = ethTxManagerClient.Add(ctx, owner, id, from, to, value, data, nil) + require.NoError(t, err) + + go ethTxManagerClient.Start() + + time.Sleep(time.Second) + result, err := ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, id, result.ID) + require.Equal(t, MonitoredTxStatusConfirmed, result.Status) + require.Equal(t, 1, len(result.Txs)) + require.Equal(t, signedTx, result.Txs[signedTx.Hash()].Tx) + require.Equal(t, receipt, result.Txs[signedTx.Hash()].Receipt) + require.Equal(t, "", result.Txs[signedTx.Hash()].RevertMessage) +} + +func TestTxGetMinedAfterReviewed(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + etherman := newEthermanMock(t) + st := newStateMock(t) + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + ethTxManagerClient := New(defaultEthTxmanagerConfigForTests, etherman, storage, st) + + ctx := context.Background() + + owner := "owner" + id := "unique_id" + from := common.HexToAddress("") + var to *common.Address + var value *big.Int + var data []byte = nil + + // Add + currentNonce := uint64(1) + etherman. + On("CurrentNonce", ctx, from). + Return(currentNonce, nil). + Once() + + firstGasEstimation := uint64(1) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(firstGasEstimation, nil). + Once() + + firstGasPriceSuggestion := big.NewInt(1) + etherman. + On("SuggestedGasPrice", ctx). + Return(firstGasPriceSuggestion, nil). + Once() + + // Monitoring Cycle 1 + firstSignedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: firstGasEstimation, + GasPrice: firstGasPriceSuggestion, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(firstSignedTx, nil). + Once() + etherman. + On("GetTx", ctx, firstSignedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("SendTx", ctx, firstSignedTx). + Return(nil). + Once() + etherman. + On("WaitTxToBeMined", ctx, firstSignedTx, mock.IsType(time.Second)). + Return(false, errors.New("tx not mined yet")). + Once() + + // Monitoring Cycle 2 + etherman. + On("CheckTxWasMined", ctx, firstSignedTx.Hash()). + Return(false, nil, nil). + Once() + + secondGasEstimation := uint64(2) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(secondGasEstimation, nil). + Once() + secondGasPriceSuggestion := big.NewInt(2) + etherman. + On("SuggestedGasPrice", ctx). + Return(secondGasPriceSuggestion, nil). + Once() + + secondSignedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: secondGasEstimation, + GasPrice: secondGasPriceSuggestion, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(secondSignedTx, nil). + Once() + etherman. + On("GetTx", ctx, secondSignedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("SendTx", ctx, secondSignedTx). + Return(nil). + Once() + etherman. + On("WaitTxToBeMined", ctx, secondSignedTx, mock.IsType(time.Second)). + Run(func(args mock.Arguments) { ethTxManagerClient.Stop() }). // stops the management cycle to avoid problems with mocks + Return(true, nil). + Once() + + blockNumber := big.NewInt(1) + + receipt := ðTypes.Receipt{ + BlockNumber: blockNumber, + Status: ethTypes.ReceiptStatusSuccessful, + } + etherman. + On("GetTxReceipt", ctx, secondSignedTx.Hash()). + Return(receipt, nil). + Once() + + block := &state.Block{ + BlockNumber: blockNumber.Uint64(), + } + st. + On("GetLastBlock", ctx, nil). + Return(block, nil). + Once() + + // Build result + etherman. + On("GetTx", ctx, firstSignedTx.Hash()). + Return(firstSignedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, firstSignedTx.Hash()). + Return(nil, ethereum.NotFound). + Once() + etherman. + On("GetRevertMessage", ctx, firstSignedTx). + Return("", nil). + Once() + etherman. + On("GetTx", ctx, secondSignedTx.Hash()). + Return(secondSignedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, secondSignedTx.Hash()). + Return(receipt, nil). + Once() + etherman. + On("GetRevertMessage", ctx, secondSignedTx). + Return("", nil). + Once() + + err = ethTxManagerClient.Add(ctx, owner, id, from, to, value, data, nil) + require.NoError(t, err) + + go ethTxManagerClient.Start() + + time.Sleep(time.Second) + result, err := ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, MonitoredTxStatusConfirmed, result.Status) +} + +func TestTxGetMinedAfterConfirmedAndReorged(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + etherman := newEthermanMock(t) + st := newStateMock(t) + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + ethTxManagerClient := New(defaultEthTxmanagerConfigForTests, etherman, storage, st) + + owner := "owner" + id := "unique_id" + from := common.HexToAddress("") + var to *common.Address + var value *big.Int + var data []byte = nil + + ctx := context.Background() + + // Add + currentNonce := uint64(1) + etherman. + On("CurrentNonce", ctx, from). + Return(currentNonce, nil). + Once() + + estimatedGas := uint64(1) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(estimatedGas, nil). + Once() + + suggestedGasPrice := big.NewInt(1) + etherman. + On("SuggestedGasPrice", ctx). + Return(suggestedGasPrice, nil). + Once() + + // Monitoring Cycle 1 + signedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: estimatedGas, + GasPrice: suggestedGasPrice, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(signedTx, nil). + Once() + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("SendTx", ctx, signedTx). + Return(nil). + Once() + etherman. + On("WaitTxToBeMined", ctx, signedTx, mock.IsType(time.Second)). + Return(true, nil). + Once() + + blockNumber := big.NewInt(10) + + receipt := ðTypes.Receipt{ + BlockNumber: blockNumber, + Status: ethTypes.ReceiptStatusSuccessful, + } + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Return(receipt, nil). + Once() + + block := &state.Block{ + BlockNumber: blockNumber.Uint64(), + } + st. + On("GetLastBlock", ctx, nil). + Run(func(args mock.Arguments) { ethTxManagerClient.Stop() }). // stops the management cycle to avoid problems with mocks + Return(block, nil). + Once() + + // Build Result 1 + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(signedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Return(receipt, nil). + Once() + etherman. + On("GetRevertMessage", ctx, signedTx). + Return("", nil). + Once() + + // Build Result 2 + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Return(nil, ethereum.NotFound). + Once() + var nilTxPtr *ethTypes.Transaction + etherman. + On("GetRevertMessage", ctx, nilTxPtr). + Return("", nil). + Once() + + // Monitoring Cycle 2 + etherman. + On("CheckTxWasMined", ctx, signedTx.Hash()). + Return(false, nil, nil). + Once() + + // Monitoring Cycle 3 + etherman. + On("CheckTxWasMined", ctx, signedTx.Hash()). + Return(true, receipt, nil). + Once() + st. + On("GetLastBlock", ctx, nil). + Run(func(args mock.Arguments) { ethTxManagerClient.Stop() }). // stops the management cycle to avoid problems with mocks + Return(block, nil). + Once() + + // Build Result 3 + etherman. + On("GetTx", ctx, signedTx.Hash()). + Return(signedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, signedTx.Hash()). + Return(receipt, nil). + Once() + etherman. + On("GetRevertMessage", ctx, signedTx). + Return("", nil). + Once() + + err = ethTxManagerClient.Add(ctx, owner, id, from, to, value, data, nil) + require.NoError(t, err) + + go ethTxManagerClient.Start() + + time.Sleep(time.Second) + result, err := ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, id, result.ID) + require.Equal(t, MonitoredTxStatusConfirmed, result.Status) + require.Equal(t, 1, len(result.Txs)) + require.Equal(t, signedTx, result.Txs[signedTx.Hash()].Tx) + require.Equal(t, receipt, result.Txs[signedTx.Hash()].Receipt) + require.Equal(t, "", result.Txs[signedTx.Hash()].RevertMessage) + + err = ethTxManagerClient.Reorg(ctx, blockNumber.Uint64()-3, nil) + require.NoError(t, err) + + result, err = ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, id, result.ID) + require.Equal(t, MonitoredTxStatusReorged, result.Status) + require.Equal(t, 1, len(result.Txs)) + require.Nil(t, result.Txs[signedTx.Hash()].Tx) + require.Nil(t, result.Txs[signedTx.Hash()].Receipt) + require.Equal(t, "", result.Txs[signedTx.Hash()].RevertMessage) + + // creates a new instance of client to avoid a race condition in the test code + ethTxManagerClient = New(defaultEthTxmanagerConfigForTests, etherman, storage, st) + + go ethTxManagerClient.Start() + + time.Sleep(time.Second) + result, err = ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, id, result.ID) + require.Equal(t, MonitoredTxStatusConfirmed, result.Status) + require.Equal(t, 1, len(result.Txs)) + require.Equal(t, signedTx, result.Txs[signedTx.Hash()].Tx) + require.Equal(t, receipt, result.Txs[signedTx.Hash()].Receipt) + require.Equal(t, "", result.Txs[signedTx.Hash()].RevertMessage) +} + +func TestExecutionReverted(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + etherman := newEthermanMock(t) + st := newStateMock(t) + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + ethTxManagerClient := New(defaultEthTxmanagerConfigForTests, etherman, storage, st) + + ctx := context.Background() + + owner := "owner" + id := "unique_id" + from := common.HexToAddress("") + var to *common.Address + var value *big.Int + var data []byte = nil + + // Add + currentNonce := uint64(1) + etherman. + On("CurrentNonce", ctx, from). + Return(currentNonce, nil). + Once() + + firstGasEstimation := uint64(1) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(firstGasEstimation, nil). + Once() + + firstGasPriceSuggestion := big.NewInt(1) + etherman. + On("SuggestedGasPrice", ctx). + Return(firstGasPriceSuggestion, nil). + Once() + + // Monitoring Cycle 1 + firstSignedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: firstGasEstimation, + GasPrice: firstGasPriceSuggestion, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(firstSignedTx, nil). + Once() + etherman. + On("GetTx", ctx, firstSignedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("SendTx", ctx, firstSignedTx). + Return(nil). + Once() + etherman. + On("WaitTxToBeMined", ctx, firstSignedTx, mock.IsType(time.Second)). + Return(true, nil). + Once() + + blockNumber := big.NewInt(1) + failedReceipt := ðTypes.Receipt{ + BlockNumber: blockNumber, + Status: ethTypes.ReceiptStatusFailed, + TxHash: firstSignedTx.Hash(), + } + + etherman. + On("GetTxReceipt", ctx, firstSignedTx.Hash()). + Return(failedReceipt, nil). + Once() + etherman. + On("GetTx", ctx, firstSignedTx.Hash()). + Return(firstSignedTx, false, nil). + Once() + etherman. + On("GetRevertMessage", ctx, firstSignedTx). + Return("", ErrExecutionReverted). + Once() + + // Monitoring Cycle 2 + etherman. + On("CheckTxWasMined", ctx, firstSignedTx.Hash()). + Return(true, failedReceipt, nil). + Once() + + currentNonce = uint64(2) + etherman. + On("CurrentNonce", ctx, from). + Return(currentNonce, nil). + Once() + secondGasEstimation := uint64(2) + etherman. + On("EstimateGas", ctx, from, to, value, data). + Return(secondGasEstimation, nil). + Once() + secondGasPriceSuggestion := big.NewInt(2) + etherman. + On("SuggestedGasPrice", ctx). + Return(secondGasPriceSuggestion, nil). + Once() + + secondSignedTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: currentNonce, + To: to, + Value: value, + Gas: secondGasEstimation, + GasPrice: secondGasPriceSuggestion, + Data: data, + }) + etherman. + On("SignTx", ctx, from, mock.IsType(ðTypes.Transaction{})). + Return(secondSignedTx, nil). + Once() + etherman. + On("GetTx", ctx, secondSignedTx.Hash()). + Return(nil, false, ethereum.NotFound). + Once() + etherman. + On("SendTx", ctx, secondSignedTx). + Return(nil). + Once() + etherman. + On("WaitTxToBeMined", ctx, secondSignedTx, mock.IsType(time.Second)). + Run(func(args mock.Arguments) { ethTxManagerClient.Stop() }). // stops the management cycle to avoid problems with mocks + Return(true, nil). + Once() + + blockNumber = big.NewInt(2) + receipt := ðTypes.Receipt{ + BlockNumber: blockNumber, + Status: ethTypes.ReceiptStatusSuccessful, + } + etherman. + On("GetTxReceipt", ctx, secondSignedTx.Hash()). + Return(receipt, nil). + Once() + + block := &state.Block{ + BlockNumber: blockNumber.Uint64(), + } + st. + On("GetLastBlock", ctx, nil). + Return(block, nil). + Once() + + // Build result + etherman. + On("GetTx", ctx, firstSignedTx.Hash()). + Return(firstSignedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, firstSignedTx.Hash()). + Return(nil, ethereum.NotFound). + Once() + etherman. + On("GetRevertMessage", ctx, firstSignedTx). + Return("", nil). + Once() + etherman. + On("GetTx", ctx, secondSignedTx.Hash()). + Return(secondSignedTx, false, nil). + Once() + etherman. + On("GetTxReceipt", ctx, secondSignedTx.Hash()). + Return(receipt, nil). + Once() + etherman. + On("GetRevertMessage", ctx, secondSignedTx). + Return("", nil). + Once() + + err = ethTxManagerClient.Add(ctx, owner, id, from, to, value, data, nil) + require.NoError(t, err) + + go ethTxManagerClient.Start() + + time.Sleep(time.Second) + result, err := ethTxManagerClient.Result(ctx, owner, id, nil) + require.NoError(t, err) + require.Equal(t, MonitoredTxStatusConfirmed, result.Status) } diff --git a/ethtxmanager/interfaces.go b/ethtxmanager/interfaces.go index a6b5ced1bf..304e6fd100 100644 --- a/ethtxmanager/interfaces.go +++ b/ethtxmanager/interfaces.go @@ -5,18 +5,33 @@ import ( "math/big" "time" - ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" ) -type etherman interface { - SequenceBatches(sequences []ethmanTypes.Sequence, gasLimit uint64, gasPrice, nonce *big.Int) (*types.Transaction, error) - VerifyBatch(batchNumber uint64, resGetProof *pb.GetProofResponse, gasLimit uint64, gasPrice, nonce *big.Int) (*types.Transaction, error) - EstimateGasForVerifyBatch(batchNumber uint64, resGetProof *pb.GetProofResponse) (uint64, error) - EstimateGasSequenceBatches(sequences []ethmanTypes.Sequence) (*types.Transaction, error) +type ethermanInterface interface { GetTx(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) GetTxReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - WaitTxToBeMined(hash common.Hash, timeout time.Duration) error + WaitTxToBeMined(ctx context.Context, tx *types.Transaction, timeout time.Duration) (bool, error) + SendTx(ctx context.Context, tx *types.Transaction) error + CurrentNonce(ctx context.Context, account common.Address) (uint64, error) + SuggestedGasPrice(ctx context.Context) (*big.Int, error) + EstimateGas(ctx context.Context, from common.Address, to *common.Address, value *big.Int, data []byte) (uint64, error) + CheckTxWasMined(ctx context.Context, txHash common.Hash) (bool, *types.Receipt, error) + SignTx(ctx context.Context, sender common.Address, tx *types.Transaction) (*types.Transaction, error) + GetRevertMessage(ctx context.Context, tx *types.Transaction) (string, error) +} + +type storageInterface interface { + Add(ctx context.Context, mTx monitoredTx, dbTx pgx.Tx) error + Get(ctx context.Context, owner, id string, dbTx pgx.Tx) (monitoredTx, error) + GetByStatus(ctx context.Context, owner *string, statuses []MonitoredTxStatus, dbTx pgx.Tx) ([]monitoredTx, error) + GetByBlock(ctx context.Context, fromBlock, toBlock *uint64, dbTx pgx.Tx) ([]monitoredTx, error) + Update(ctx context.Context, mTx monitoredTx, dbTx pgx.Tx) error +} + +type stateInterface interface { + GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) } diff --git a/ethtxmanager/mock_etherman_test.go b/ethtxmanager/mock_etherman_test.go new file mode 100644 index 0000000000..55fef0ddbe --- /dev/null +++ b/ethtxmanager/mock_etherman_test.go @@ -0,0 +1,290 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package ethtxmanager + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + time "time" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// ethermanMock is an autogenerated mock type for the ethermanInterface type +type ethermanMock struct { + mock.Mock +} + +// CheckTxWasMined provides a mock function with given fields: ctx, txHash +func (_m *ethermanMock) CheckTxWasMined(ctx context.Context, txHash common.Hash) (bool, *types.Receipt, error) { + ret := _m.Called(ctx, txHash) + + var r0 bool + var r1 *types.Receipt + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (bool, *types.Receipt, error)); ok { + return rf(ctx, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) bool); ok { + r0 = rf(ctx, txHash) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) *types.Receipt); ok { + r1 = rf(ctx, txHash) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*types.Receipt) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, common.Hash) error); ok { + r2 = rf(ctx, txHash) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// CurrentNonce provides a mock function with given fields: ctx, account +func (_m *ethermanMock) CurrentNonce(ctx context.Context, account common.Address) (uint64, error) { + ret := _m.Called(ctx, account) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) (uint64, error)); ok { + return rf(ctx, account) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address) uint64); ok { + r0 = rf(ctx, account) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { + r1 = rf(ctx, account) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EstimateGas provides a mock function with given fields: ctx, from, to, value, data +func (_m *ethermanMock) EstimateGas(ctx context.Context, from common.Address, to *common.Address, value *big.Int, data []byte) (uint64, error) { + ret := _m.Called(ctx, from, to, value, data) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *common.Address, *big.Int, []byte) (uint64, error)); ok { + return rf(ctx, from, to, value, data) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *common.Address, *big.Int, []byte) uint64); ok { + r0 = rf(ctx, from, to, value, data) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *common.Address, *big.Int, []byte) error); ok { + r1 = rf(ctx, from, to, value, data) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetRevertMessage provides a mock function with given fields: ctx, tx +func (_m *ethermanMock) GetRevertMessage(ctx context.Context, tx *types.Transaction) (string, error) { + ret := _m.Called(ctx, tx) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) (string, error)); ok { + return rf(ctx, tx) + } + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) string); ok { + r0 = rf(ctx, tx) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction) error); ok { + r1 = rf(ctx, tx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTx provides a mock function with given fields: ctx, txHash +func (_m *ethermanMock) GetTx(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) { + ret := _m.Called(ctx, txHash) + + var r0 *types.Transaction + var r1 bool + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Transaction, bool, error)); ok { + return rf(ctx, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Transaction); ok { + r0 = rf(ctx, txHash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) bool); ok { + r1 = rf(ctx, txHash) + } else { + r1 = ret.Get(1).(bool) + } + + if rf, ok := ret.Get(2).(func(context.Context, common.Hash) error); ok { + r2 = rf(ctx, txHash) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetTxReceipt provides a mock function with given fields: ctx, txHash +func (_m *ethermanMock) GetTxReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { + ret := _m.Called(ctx, txHash) + + var r0 *types.Receipt + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*types.Receipt, error)); ok { + return rf(ctx, txHash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *types.Receipt); ok { + r0 = rf(ctx, txHash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Receipt) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, txHash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SendTx provides a mock function with given fields: ctx, tx +func (_m *ethermanMock) SendTx(ctx context.Context, tx *types.Transaction) error { + ret := _m.Called(ctx, tx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction) error); ok { + r0 = rf(ctx, tx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SignTx provides a mock function with given fields: ctx, sender, tx +func (_m *ethermanMock) SignTx(ctx context.Context, sender common.Address, tx *types.Transaction) (*types.Transaction, error) { + ret := _m.Called(ctx, sender, tx) + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error)); ok { + return rf(ctx, sender, tx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *types.Transaction) *types.Transaction); ok { + r0 = rf(ctx, sender, tx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *types.Transaction) error); ok { + r1 = rf(ctx, sender, tx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SuggestedGasPrice provides a mock function with given fields: ctx +func (_m *ethermanMock) SuggestedGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// WaitTxToBeMined provides a mock function with given fields: ctx, tx, timeout +func (_m *ethermanMock) WaitTxToBeMined(ctx context.Context, tx *types.Transaction, timeout time.Duration) (bool, error) { + ret := _m.Called(ctx, tx, timeout) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, time.Duration) (bool, error)); ok { + return rf(ctx, tx, timeout) + } + if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, time.Duration) bool); ok { + r0 = rf(ctx, tx, timeout) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, *types.Transaction, time.Duration) error); ok { + r1 = rf(ctx, tx, timeout) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTnewEthermanMock interface { + mock.TestingT + Cleanup(func()) +} + +// newEthermanMock creates a new instance of ethermanMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newEthermanMock(t mockConstructorTestingTnewEthermanMock) *ethermanMock { + mock := ðermanMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ethtxmanager/mock_state_test.go b/ethtxmanager/mock_state_test.go new file mode 100644 index 0000000000..befb59638c --- /dev/null +++ b/ethtxmanager/mock_state_test.go @@ -0,0 +1,59 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package ethtxmanager + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" + + state "github.com/0xPolygonHermez/zkevm-node/state" +) + +// stateMock is an autogenerated mock type for the stateInterface type +type stateMock struct { + mock.Mock +} + +// GetLastBlock provides a mock function with given fields: ctx, dbTx +func (_m *stateMock) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Block, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Block); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTnewStateMock interface { + mock.TestingT + Cleanup(func()) +} + +// newStateMock creates a new instance of stateMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newStateMock(t mockConstructorTestingTnewStateMock) *stateMock { + mock := &stateMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ethtxmanager/monitoredtx.go b/ethtxmanager/monitoredtx.go new file mode 100644 index 0000000000..47a344b967 --- /dev/null +++ b/ethtxmanager/monitoredtx.go @@ -0,0 +1,192 @@ +package ethtxmanager + +import ( + "encoding/hex" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +const ( + // MonitoredTxStatusCreated mean the tx was just added to the storage + MonitoredTxStatusCreated = MonitoredTxStatus("created") + + // MonitoredTxStatusSent means that at least a eth tx was sent to the network + MonitoredTxStatusSent = MonitoredTxStatus("sent") + + // MonitoredTxStatusFailed means the tx was already mined and failed with an + // error that can't be recovered automatically, ex: the data in the tx is invalid + // and the tx gets reverted + MonitoredTxStatusFailed = MonitoredTxStatus("failed") + + // MonitoredTxStatusConfirmed means the tx was already mined and the receipt + // status is Successful + MonitoredTxStatusConfirmed = MonitoredTxStatus("confirmed") + + // MonitoredTxStatusReorged is used when a monitored tx was already confirmed but + // the L1 block where this tx was confirmed has been reorged, in this situation + // the caller needs to review this information and wait until it gets confirmed + // again in a future block + MonitoredTxStatusReorged = MonitoredTxStatus("reorged") + + // MonitoredTxStatusDone means the tx was set by the owner as done + MonitoredTxStatusDone = MonitoredTxStatus("done") +) + +// MonitoredTxStatus represents the status of a monitored tx +type MonitoredTxStatus string + +// String returns a string representation of the status +func (s MonitoredTxStatus) String() string { + return string(s) +} + +// monitoredTx represents a set of information used to build tx +// plus information to monitor if the transactions was sent successfully +type monitoredTx struct { + // owner is the common identifier among all the monitored tx to identify who + // created this, it's a identification provided by the caller in order to be + // used in the future to query the monitored tx by the owner, this allows the + // caller to be free of implementing a persistence layer to monitor the txs + owner string + + // id is the tx identifier controller by the caller + id string + + // sender of the tx, used to identify which private key should be used to sing the tx + from common.Address + + // receiver of the tx + to *common.Address + + // nonce used to create the tx + nonce uint64 + + // tx value + value *big.Int + + // tx data + data []byte + + // tx gas + gas uint64 + + // tx gas price + gasPrice *big.Int + + // status of this monitoring + status MonitoredTxStatus + + // blockNumber represents the block where the tx was identified + // to be mined, it's the same as the block number found in the + // tx receipt, this is used to control reorged monitored txs + blockNumber *big.Int + + // history represent all transaction hashes from + // transactions created using this struct data and + // sent to the network + history map[common.Hash]bool + + // createdAt date time it was created + createdAt time.Time + + // updatedAt last date time it was updated + updatedAt time.Time +} + +// Tx uses the current information to build a tx +func (mTx monitoredTx) Tx() *types.Transaction { + tx := types.NewTx(&types.LegacyTx{ + To: mTx.to, + Nonce: mTx.nonce, + Value: mTx.value, + Data: mTx.data, + Gas: mTx.gas, + GasPrice: mTx.gasPrice, + }) + + return tx +} + +// AddHistory adds a transaction to the monitoring history +func (mTx monitoredTx) AddHistory(tx *types.Transaction) error { + if _, found := mTx.history[tx.Hash()]; found { + return ErrAlreadyExists + } + mTx.history[tx.Hash()] = true + return nil +} + +// toStringPtr returns the current to field as a string pointer +func (mTx *monitoredTx) toStringPtr() *string { + var to *string + if mTx.to != nil { + s := mTx.to.String() + to = &s + } + return to +} + +// valueU64Ptr returns the current value field as a uint64 pointer +func (mTx *monitoredTx) valueU64Ptr() *uint64 { + var value *uint64 + if mTx.value != nil { + tmp := mTx.value.Uint64() + value = &tmp + } + return value +} + +// dataStringPtr returns the current data field as a string pointer +func (mTx *monitoredTx) dataStringPtr() *string { + var data *string + if mTx.data != nil { + tmp := hex.EncodeToString(mTx.data) + data = &tmp + } + return data +} + +// historyStringSlice returns the current history field as a string slice +func (mTx *monitoredTx) historyStringSlice() []string { + history := make([]string, 0, len(mTx.history)) + for h := range mTx.history { + history = append(history, h.String()) + } + return history +} + +// historyHashSlice returns the current history field as a string slice +func (mTx *monitoredTx) historyHashSlice() []common.Hash { + history := make([]common.Hash, 0, len(mTx.history)) + for h := range mTx.history { + history = append(history, h) + } + return history +} + +// blockNumberU64Ptr returns the current blockNumber as a uint64 pointer +func (mTx *monitoredTx) blockNumberU64Ptr() *uint64 { + var blockNumber *uint64 + if mTx.blockNumber != nil { + tmp := mTx.blockNumber.Uint64() + blockNumber = &tmp + } + return blockNumber +} + +// MonitoredTxResult represents the result of a execution of a monitored tx +type MonitoredTxResult struct { + ID string + Status MonitoredTxStatus + Txs map[common.Hash]TxResult +} + +// TxResult represents the result of a execution of a ethereum transaction in the block chain +type TxResult struct { + Tx *types.Transaction + Receipt *types.Receipt + RevertMessage string +} diff --git a/ethtxmanager/monitoredtx_test.go b/ethtxmanager/monitoredtx_test.go new file mode 100644 index 0000000000..bfe1d4df7b --- /dev/null +++ b/ethtxmanager/monitoredtx_test.go @@ -0,0 +1,36 @@ +package ethtxmanager + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestTx(t *testing.T) { + to := common.HexToAddress("0x2") + nonce := uint64(1) + value := big.NewInt(2) + data := []byte("data") + gas := uint64(3) + gasPrice := big.NewInt(4) + + mTx := monitoredTx{ + to: &to, + nonce: nonce, + value: value, + data: data, + gas: gas, + gasPrice: gasPrice, + } + + tx := mTx.Tx() + + assert.Equal(t, &to, tx.To()) + assert.Equal(t, nonce, tx.Nonce()) + assert.Equal(t, value, tx.Value()) + assert.Equal(t, data, tx.Data()) + assert.Equal(t, gas, tx.Gas()) + assert.Equal(t, gasPrice, tx.GasPrice()) +} diff --git a/ethtxmanager/pgstorage.go b/ethtxmanager/pgstorage.go new file mode 100644 index 0000000000..b9d611cc41 --- /dev/null +++ b/ethtxmanager/pgstorage.go @@ -0,0 +1,277 @@ +package ethtxmanager + +import ( + "context" + "encoding/hex" + "errors" + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgconn" + "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v4/pgxpool" +) + +// PostgresStorage hold txs to be managed +type PostgresStorage struct { + *pgxpool.Pool +} + +// NewPostgresStorage creates a new instance of storage that use +// postgres to store data +func NewPostgresStorage(dbCfg db.Config) (*PostgresStorage, error) { + db, err := db.NewSQLDB(dbCfg) + if err != nil { + return nil, err + } + + return &PostgresStorage{ + db, + }, nil +} + +// Add persist a monitored tx +func (s *PostgresStorage) Add(ctx context.Context, mTx monitoredTx, dbTx pgx.Tx) error { + conn := s.dbConn(dbTx) + cmd := ` + INSERT INTO state.monitored_txs (owner, id, from_addr, to_addr, nonce, value, data, gas, gas_price, status, block_num, history, created_at, updated_at) + VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)` + + _, err := conn.Exec(ctx, cmd, mTx.owner, + mTx.id, mTx.from.String(), mTx.toStringPtr(), + mTx.nonce, mTx.valueU64Ptr(), mTx.dataStringPtr(), + mTx.gas, mTx.gasPrice.Uint64(), string(mTx.status), mTx.blockNumberU64Ptr(), + mTx.historyStringSlice(), time.Now().UTC().Round(time.Microsecond), + time.Now().UTC().Round(time.Microsecond)) + + if err != nil { + if pgErr, ok := err.(*pgconn.PgError); ok && pgErr.ConstraintName == "monitored_txs_pkey" { + return ErrAlreadyExists + } else { + return err + } + } + + return nil +} + +// Get loads a persisted monitored tx +func (s *PostgresStorage) Get(ctx context.Context, owner, id string, dbTx pgx.Tx) (monitoredTx, error) { + conn := s.dbConn(dbTx) + cmd := ` + SELECT owner, id, from_addr, to_addr, nonce, value, data, gas, gas_price, status, block_num, history, created_at, updated_at + FROM state.monitored_txs + WHERE owner = $1 + AND id = $2` + + mTx := monitoredTx{} + + row := conn.QueryRow(ctx, cmd, owner, id) + err := s.scanMtx(row, &mTx) + if errors.Is(err, pgx.ErrNoRows) { + return mTx, ErrNotFound + } else if err != nil { + return mTx, err + } + + return mTx, nil +} + +// GetByStatus loads all monitored tx that match the provided status +func (s *PostgresStorage) GetByStatus(ctx context.Context, owner *string, statuses []MonitoredTxStatus, dbTx pgx.Tx) ([]monitoredTx, error) { + hasStatusToFilter := len(statuses) > 0 + + conn := s.dbConn(dbTx) + cmd := ` + SELECT owner, id, from_addr, to_addr, nonce, value, data, gas, gas_price, status, block_num, history, created_at, updated_at + FROM state.monitored_txs + WHERE (owner = $1 OR $1 IS NULL)` + if hasStatusToFilter { + cmd += ` + AND status = ANY($2)` + } + cmd += ` + ORDER BY created_at` + + mTxs := []monitoredTx{} + + var rows pgx.Rows + var err error + if hasStatusToFilter { + rows, err = conn.Query(ctx, cmd, owner, statuses) + } else { + rows, err = conn.Query(ctx, cmd, owner) + } + + if errors.Is(err, pgx.ErrNoRows) { + return []monitoredTx{}, nil + } else if err != nil { + return nil, err + } + + for rows.Next() { + mTx := monitoredTx{} + err := s.scanMtx(rows, &mTx) + if err != nil { + return nil, err + } + mTxs = append(mTxs, mTx) + } + + return mTxs, nil +} + +// GetByBlock loads all monitored tx that have the blockNumber between +// fromBlock and toBlock +func (s *PostgresStorage) GetByBlock(ctx context.Context, fromBlock, toBlock *uint64, dbTx pgx.Tx) ([]monitoredTx, error) { + conn := s.dbConn(dbTx) + cmd := ` + SELECT owner, id, from_addr, to_addr, nonce, value, data, gas, gas_price, status, block_num, history, created_at, updated_at + FROM state.monitored_txs + WHERE (block_num >= $1 OR $1 IS NULL) + AND (block_num <= $2 OR $2 IS NULL) + AND block_num IS NOT NULL + ORDER BY created_at` + + const numberOfArgs = 2 + args := make([]interface{}, 0, numberOfArgs) + + if fromBlock != nil { + args = append(args, *fromBlock) + } else { + args = append(args, fromBlock) + } + + if toBlock != nil { + args = append(args, *toBlock) + } else { + args = append(args, toBlock) + } + + mTxs := []monitoredTx{} + rows, err := conn.Query(ctx, cmd, args...) + + if errors.Is(err, pgx.ErrNoRows) { + return []monitoredTx{}, nil + } else if err != nil { + return nil, err + } + + for rows.Next() { + mTx := monitoredTx{} + err := s.scanMtx(rows, &mTx) + if err != nil { + return nil, err + } + mTxs = append(mTxs, mTx) + } + + return mTxs, nil +} + +// Update a persisted monitored tx +func (s *PostgresStorage) Update(ctx context.Context, mTx monitoredTx, dbTx pgx.Tx) error { + conn := s.dbConn(dbTx) + cmd := ` + UPDATE state.monitored_txs + SET from_addr = $3 + , to_addr = $4 + , nonce = $5 + , value = $6 + , data = $7 + , gas = $8 + , gas_price = $9 + , status = $10 + , block_num = $11 + , history = $12 + , updated_at = $13 + WHERE owner = $1 + AND id = $2` + + var bn *uint64 + if mTx.blockNumber != nil { + tmp := mTx.blockNumber.Uint64() + bn = &tmp + } + + _, err := conn.Exec(ctx, cmd, mTx.owner, + mTx.id, mTx.from.String(), mTx.toStringPtr(), + mTx.nonce, mTx.valueU64Ptr(), mTx.dataStringPtr(), + mTx.gas, mTx.gasPrice.Uint64(), string(mTx.status), bn, + mTx.historyStringSlice(), time.Now().UTC().Round(time.Microsecond)) + + if err != nil { + return err + } + + return nil +} + +// scanMtx scans a row and fill the provided instance of monitoredTx with +// the row data +func (s *PostgresStorage) scanMtx(row pgx.Row, mTx *monitoredTx) error { + // id, from, to, nonce, value, data, gas, gas_price, status, history, created_at, updated_at + var from, status string + var to, data *string + var history []string + var value, blockNumber *uint64 + var gasPrice uint64 + + err := row.Scan(&mTx.owner, &mTx.id, &from, &to, &mTx.nonce, &value, + &data, &mTx.gas, &gasPrice, &status, &blockNumber, &history, + &mTx.createdAt, &mTx.updatedAt) + if err != nil { + return err + } + + mTx.from = common.HexToAddress(from) + mTx.gasPrice = big.NewInt(0).SetUint64(gasPrice) + mTx.status = MonitoredTxStatus(status) + + if to != nil { + tmp := common.HexToAddress(*to) + mTx.to = &tmp + } + if value != nil { + tmp := *value + mTx.value = big.NewInt(0).SetUint64(tmp) + } + if data != nil { + tmp := *data + bytes, err := hex.DecodeString(tmp) + if err != nil { + return err + } + mTx.data = bytes + } + if blockNumber != nil { + tmp := *blockNumber + mTx.blockNumber = big.NewInt(0).SetUint64(tmp) + } + + h := make(map[common.Hash]bool, len(history)) + for _, txHash := range history { + h[common.HexToHash(txHash)] = true + } + mTx.history = h + + return nil +} + +// dbConn represents an instance of an object that can +// connect to a postgres db to execute sql commands and query data +type dbConn interface { + Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error) + Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) + QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row +} + +// dbConn determines which db connection to use, dbTx or the main pgxpool +func (p *PostgresStorage) dbConn(dbTx pgx.Tx) dbConn { + if dbTx != nil { + return dbTx + } + return p +} diff --git a/ethtxmanager/pgstorage_test.go b/ethtxmanager/pgstorage_test.go new file mode 100644 index 0000000000..be20b2d498 --- /dev/null +++ b/ethtxmanager/pgstorage_test.go @@ -0,0 +1,300 @@ +package ethtxmanager + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAddGetAndUpdate(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + owner := "owner" + id := "id" + from := common.HexToAddress("0x1") + to := common.HexToAddress("0x2") + nonce := uint64(1) + value := big.NewInt(2) + data := []byte("data") + gas := uint64(3) + gasPrice := big.NewInt(4) + status := MonitoredTxStatusCreated + blockNumber := big.NewInt(5) + history := map[common.Hash]bool{common.HexToHash("0x3"): true, common.HexToHash("0x4"): true} + + mTx := monitoredTx{ + owner: owner, id: id, from: from, to: &to, nonce: nonce, value: value, data: data, + blockNumber: blockNumber, gas: gas, gasPrice: gasPrice, status: status, history: history, + } + err = storage.Add(context.Background(), mTx, nil) + require.NoError(t, err) + + returnedMtx, err := storage.Get(context.Background(), owner, id, nil) + require.NoError(t, err) + + assert.Equal(t, owner, returnedMtx.owner) + assert.Equal(t, id, returnedMtx.id) + assert.Equal(t, from.String(), returnedMtx.from.String()) + assert.Equal(t, to.String(), returnedMtx.to.String()) + assert.Equal(t, nonce, returnedMtx.nonce) + assert.Equal(t, value, returnedMtx.value) + assert.Equal(t, data, returnedMtx.data) + assert.Equal(t, gas, returnedMtx.gas) + assert.Equal(t, gasPrice, returnedMtx.gasPrice) + assert.Equal(t, status, returnedMtx.status) + assert.Equal(t, 0, blockNumber.Cmp(returnedMtx.blockNumber)) + assert.Equal(t, history, returnedMtx.history) + assert.Greater(t, time.Now().UTC().Round(time.Microsecond), returnedMtx.createdAt) + assert.Less(t, time.Time{}, returnedMtx.createdAt) + assert.Greater(t, time.Now().UTC().Round(time.Microsecond), returnedMtx.updatedAt) + assert.Less(t, time.Time{}, returnedMtx.updatedAt) + + from = common.HexToAddress("0x11") + to = common.HexToAddress("0x22") + nonce = uint64(11) + value = big.NewInt(22) + data = []byte("data data") + gas = uint64(33) + gasPrice = big.NewInt(44) + status = MonitoredTxStatusFailed + blockNumber = big.NewInt(55) + history = map[common.Hash]bool{common.HexToHash("0x33"): true, common.HexToHash("0x44"): true} + + mTx = monitoredTx{ + owner: owner, id: id, from: from, to: &to, nonce: nonce, value: value, data: data, + blockNumber: blockNumber, gas: gas, gasPrice: gasPrice, status: status, history: history, + } + err = storage.Update(context.Background(), mTx, nil) + require.NoError(t, err) + + returnedMtx, err = storage.Get(context.Background(), owner, id, nil) + require.NoError(t, err) + + assert.Equal(t, owner, returnedMtx.owner) + assert.Equal(t, id, returnedMtx.id) + assert.Equal(t, from.String(), returnedMtx.from.String()) + assert.Equal(t, to.String(), returnedMtx.to.String()) + assert.Equal(t, nonce, returnedMtx.nonce) + assert.Equal(t, value, returnedMtx.value) + assert.Equal(t, data, returnedMtx.data) + assert.Equal(t, gas, returnedMtx.gas) + assert.Equal(t, gasPrice, returnedMtx.gasPrice) + assert.Equal(t, status, returnedMtx.status) + assert.Equal(t, 0, blockNumber.Cmp(returnedMtx.blockNumber)) + assert.Equal(t, history, returnedMtx.history) + assert.Greater(t, time.Now().UTC().Round(time.Microsecond), returnedMtx.createdAt) + assert.Less(t, time.Time{}, returnedMtx.createdAt) + assert.Greater(t, time.Now().UTC().Round(time.Microsecond), returnedMtx.updatedAt) + assert.Less(t, time.Time{}, returnedMtx.updatedAt) +} + +func TestAddAndGetByStatus(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + to := common.HexToAddress("0x2") + baseMtx := monitoredTx{ + owner: "owner", from: common.HexToAddress("0x1"), to: &to, nonce: uint64(1), value: big.NewInt(2), data: []byte("data"), blockNumber: big.NewInt(1), + gas: uint64(3), gasPrice: big.NewInt(4), history: map[common.Hash]bool{common.HexToHash("0x3"): true, common.HexToHash("0x4"): true}, + } + + type mTxReplaceInfo struct { + id string + status MonitoredTxStatus + } + + mTxsReplaceInfo := []mTxReplaceInfo{ + {id: "created1", status: MonitoredTxStatusCreated}, + {id: "sent1", status: MonitoredTxStatusSent}, + {id: "failed1", status: MonitoredTxStatusFailed}, + {id: "confirmed1", status: MonitoredTxStatusConfirmed}, + {id: "created2", status: MonitoredTxStatusCreated}, + {id: "sent2", status: MonitoredTxStatusSent}, + {id: "failed2", status: MonitoredTxStatusFailed}, + {id: "confirmed2", status: MonitoredTxStatusConfirmed}, + } + + for _, replaceInfo := range mTxsReplaceInfo { + baseMtx.id = replaceInfo.id + baseMtx.status = replaceInfo.status + baseMtx.createdAt = baseMtx.createdAt.Add(time.Microsecond) + baseMtx.updatedAt = baseMtx.updatedAt.Add(time.Microsecond) + err = storage.Add(context.Background(), baseMtx, nil) + require.NoError(t, err) + } + + mTxs, err := storage.GetByStatus(context.Background(), nil, []MonitoredTxStatus{MonitoredTxStatusConfirmed}, nil) + require.NoError(t, err) + assert.Equal(t, 2, len(mTxs)) + assert.Equal(t, "confirmed1", mTxs[0].id) + assert.Equal(t, "confirmed2", mTxs[1].id) + + mTxs, err = storage.GetByStatus(context.Background(), nil, []MonitoredTxStatus{MonitoredTxStatusSent, MonitoredTxStatusCreated}, nil) + require.NoError(t, err) + assert.Equal(t, 4, len(mTxs)) + assert.Equal(t, "created1", mTxs[0].id) + assert.Equal(t, "sent1", mTxs[1].id) + assert.Equal(t, "created2", mTxs[2].id) + assert.Equal(t, "sent2", mTxs[3].id) + + mTxs, err = storage.GetByStatus(context.Background(), nil, []MonitoredTxStatus{}, nil) + require.NoError(t, err) + assert.Equal(t, 8, len(mTxs)) + assert.Equal(t, "created1", mTxs[0].id) + assert.Equal(t, "sent1", mTxs[1].id) + assert.Equal(t, "failed1", mTxs[2].id) + assert.Equal(t, "confirmed1", mTxs[3].id) + assert.Equal(t, "created2", mTxs[4].id) + assert.Equal(t, "sent2", mTxs[5].id) + assert.Equal(t, "failed2", mTxs[6].id) + assert.Equal(t, "confirmed2", mTxs[7].id) +} + +func TestAddRepeated(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + owner := "owner" + id := "id" + from := common.HexToAddress("0x1") + to := common.HexToAddress("0x2") + nonce := uint64(1) + value := big.NewInt(2) + data := []byte("data") + gas := uint64(3) + gasPrice := big.NewInt(4) + blockNumber := big.NewInt(5) + status := MonitoredTxStatusCreated + history := map[common.Hash]bool{common.HexToHash("0x3"): true, common.HexToHash("0x4"): true} + + mTx := monitoredTx{ + owner: owner, id: id, from: from, to: &to, nonce: nonce, value: value, data: data, + blockNumber: blockNumber, gas: gas, gasPrice: gasPrice, status: status, history: history, + } + err = storage.Add(context.Background(), mTx, nil) + require.NoError(t, err) + + err = storage.Add(context.Background(), mTx, nil) + require.Equal(t, ErrAlreadyExists, err) +} + +func TestGetNotFound(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + _, err = storage.Get(context.Background(), "not found owner", "not found id", nil) + require.Equal(t, ErrNotFound, err) +} + +func TestGetByStatusNoRows(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + mTxs, err := storage.GetByStatus(context.Background(), nil, []MonitoredTxStatus{}, nil) + require.NoError(t, err) + require.Empty(t, mTxs) +} + +func TestAddAndGetByBlock(t *testing.T) { + dbCfg := dbutils.NewStateConfigFromEnv() + require.NoError(t, dbutils.InitOrResetState(dbCfg)) + + storage, err := NewPostgresStorage(dbCfg) + require.NoError(t, err) + + to := common.HexToAddress("0x2") + baseMtx := monitoredTx{ + owner: "owner", from: common.HexToAddress("0x1"), to: &to, nonce: uint64(1), value: big.NewInt(2), data: []byte("data"), blockNumber: big.NewInt(1), + gas: uint64(3), gasPrice: big.NewInt(4), history: map[common.Hash]bool{common.HexToHash("0x3"): true, common.HexToHash("0x4"): true}, + } + + type mTxReplaceInfo struct { + id string + blockNumber *big.Int + } + + mTxsReplaceInfo := []mTxReplaceInfo{ + {id: "1", blockNumber: nil}, + {id: "2", blockNumber: big.NewInt(2)}, + {id: "3", blockNumber: big.NewInt(3)}, + {id: "4", blockNumber: big.NewInt(4)}, + {id: "5", blockNumber: big.NewInt(5)}, + } + + for _, replaceInfo := range mTxsReplaceInfo { + baseMtx.id = replaceInfo.id + baseMtx.blockNumber = replaceInfo.blockNumber + baseMtx.createdAt = baseMtx.createdAt.Add(time.Microsecond) + baseMtx.updatedAt = baseMtx.updatedAt.Add(time.Microsecond) + err = storage.Add(context.Background(), baseMtx, nil) + require.NoError(t, err) + } + + // all monitored txs + mTxs, err := storage.GetByBlock(context.Background(), nil, nil, nil) + require.NoError(t, err) + assert.Equal(t, 4, len(mTxs)) + assert.Equal(t, "2", mTxs[0].id) + assert.Equal(t, 0, big.NewInt(2).Cmp(mTxs[0].blockNumber)) + assert.Equal(t, "3", mTxs[1].id) + assert.Equal(t, 0, big.NewInt(3).Cmp(mTxs[1].blockNumber)) + assert.Equal(t, "4", mTxs[2].id) + assert.Equal(t, 0, big.NewInt(4).Cmp(mTxs[2].blockNumber)) + assert.Equal(t, "5", mTxs[3].id) + assert.Equal(t, 0, big.NewInt(5).Cmp(mTxs[3].blockNumber)) + + // all monitored tx with block number less or equal 3 + toBlock := uint64(3) + mTxs, err = storage.GetByBlock(context.Background(), nil, &toBlock, nil) + require.NoError(t, err) + assert.Equal(t, 2, len(mTxs)) + assert.Equal(t, "2", mTxs[0].id) + assert.Equal(t, 0, big.NewInt(2).Cmp(mTxs[0].blockNumber)) + assert.Equal(t, "3", mTxs[1].id) + assert.Equal(t, 0, big.NewInt(3).Cmp(mTxs[1].blockNumber)) + + // all monitored tx with block number greater or equal 2 + fromBlock := uint64(3) + mTxs, err = storage.GetByBlock(context.Background(), &fromBlock, nil, nil) + require.NoError(t, err) + assert.Equal(t, 3, len(mTxs)) + assert.Equal(t, "3", mTxs[0].id) + assert.Equal(t, 0, big.NewInt(3).Cmp(mTxs[0].blockNumber)) + assert.Equal(t, "4", mTxs[1].id) + assert.Equal(t, 0, big.NewInt(4).Cmp(mTxs[1].blockNumber)) + assert.Equal(t, "5", mTxs[2].id) + assert.Equal(t, 0, big.NewInt(5).Cmp(mTxs[2].blockNumber)) + + // all monitored txs with block number between 3 and 4 inclusive + fromBlock = uint64(3) + toBlock = uint64(4) + mTxs, err = storage.GetByBlock(context.Background(), &fromBlock, &toBlock, nil) + require.NoError(t, err) + assert.Equal(t, 2, len(mTxs)) + assert.Equal(t, "3", mTxs[0].id) + assert.Equal(t, 0, big.NewInt(3).Cmp(mTxs[0].blockNumber)) + assert.Equal(t, "4", mTxs[1].id) + assert.Equal(t, 0, big.NewInt(4).Cmp(mTxs[1].blockNumber)) +} diff --git a/event/config.go b/event/config.go new file mode 100644 index 0000000000..cae1dbc8f3 --- /dev/null +++ b/event/config.go @@ -0,0 +1,9 @@ +package event + +import "github.com/0xPolygonHermez/zkevm-node/db" + +// Config for event +type Config struct { + // DB is the database configuration + DB db.Config `mapstructure:"DB"` +} diff --git a/event/event.go b/event/event.go new file mode 100644 index 0000000000..4e1e13520c --- /dev/null +++ b/event/event.go @@ -0,0 +1,90 @@ +package event + +import ( + "math/big" + "time" +) + +// EventID is the ID of the event +type EventID string + +// Source is the source of the event +type Source string + +// Component is the component that triggered the event +type Component string + +// Level is the level of the event +type Level string + +const ( + // EventID_NodeComponentStarted is triggered when the node starts + EventID_NodeComponentStarted = "NODE COMPONENT STARTED" + // EventID_PreexecutionOOC is triggered when an OOC error is detected during the preexecution + EventID_PreexecutionOOC EventID = "PRE EXECUTION OOC" + // EventID_PreexecutionOOG is triggered when an OOG error is detected during the preexecution + EventID_PreexecutionOOG EventID = "PRE EXECUTION OOG" + // EventID_ExecutorError is triggered when an error is detected during the execution + EventID_ExecutorError EventID = "EXECUTOR ERROR" + // EventID_ReprocessFullBatchOOC is triggered when an OOC error is detected during the reprocessing of a full batch + EventID_ReprocessFullBatchOOC EventID = "REPROCESS FULL BATCH OOC" + // EventID_ExecutorRLPError is triggered when an RLP error is detected during the execution + EventID_ExecutorRLPError EventID = "EXECUTOR RLP ERROR" + // EventID_FinalizerHalt is triggered when the finalizer halts + EventID_FinalizerHalt EventID = "FINALIZER HALT" + + // Source_Node is the source of the event + Source_Node Source = "node" + + // Component_RPC is the component that triggered the event + Component_RPC Component = "rpc" + // Component_Pool is the component that triggered the event + Component_Pool Component = "pool" + // Component_Sequencer is the component that triggered the event + Component_Sequencer Component = "sequencer" + // Component_Synchronizer is the component that triggered the event + Component_Synchronizer Component = "synchronizer" + // Component_Aggregator is the component that triggered the event + Component_Aggregator Component = "aggregator" + // Component_EthTxManager is the component that triggered the event + Component_EthTxManager Component = "ethtxmanager" + // Component_GasPricer is the component that triggered the event + Component_GasPricer Component = "gaspricer" + // Component_Executor is the component that triggered the event + Component_Executor Component = "executor" + // Component_Broadcast is the component that triggered the event + Component_Broadcast Component = "broadcast" + // Component_Sequence_Sender is the component that triggered the event + Component_Sequence_Sender = "seqsender" + + // Level_Emergency is the most severe level + Level_Emergency Level = "emerg" + // Level_Alert is the second most severe level + Level_Alert Level = "alert" + // Level_Critical is the third most severe level + Level_Critical Level = "crit" + // Level_Error is the fourth most severe level + Level_Error Level = "err" + // Level_Warning is the fifth most severe level + Level_Warning Level = "warning" + // Level_Notice is the sixth most severe level + Level_Notice Level = "notice" + // Level_Info is the seventh most severe level + Level_Info Level = "info" + // Level_Debug is the least severe level + Level_Debug Level = "debug" +) + +// Event represents a event that may be investigated +type Event struct { + Id big.Int + ReceivedAt time.Time + IPAddress string + Source Source + Component Component + Level Level + EventID EventID + Description string + Data []byte + Json interface{} +} diff --git a/event/eventlog.go b/event/eventlog.go new file mode 100644 index 0000000000..4c1f0ce0a9 --- /dev/null +++ b/event/eventlog.go @@ -0,0 +1,53 @@ +package event + +import ( + "context" + "encoding/json" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" +) + +// EventLog is the main struct for the event log +type EventLog struct { + cfg Config + storage Storage +} + +// NewEventLog creates and initializes an instance of EventLog +func NewEventLog(cfg Config, storage Storage) *EventLog { + return &EventLog{ + cfg: cfg, + storage: storage, + } +} + +// LogEvent is used to store an event for runtime debugging +func (e *EventLog) LogEvent(ctx context.Context, event *Event) error { + return e.storage.LogEvent(ctx, event) +} + +// LogExecutorError is used to store Executor error for runtime debugging +func (e *EventLog) LogExecutorError(ctx context.Context, responseError pb.ExecutorError, processBatchRequest *pb.ProcessBatchRequest) { + timestamp := time.Now() + log.Errorf("error found in the executor: %v at %v", responseError, timestamp) + payload, err := json.Marshal(processBatchRequest) + if err != nil { + log.Errorf("error marshaling payload: %v", err) + } else { + event := &Event{ + ReceivedAt: timestamp, + Source: Source_Node, + Component: Component_Executor, + Level: Level_Error, + EventID: EventID_ExecutorError, + Description: responseError.String(), + Json: string(payload), + } + err = e.storage.LogEvent(ctx, event) + if err != nil { + log.Errorf("error storing event: %v", err) + } + } +} diff --git a/event/eventlog_test.go b/event/eventlog_test.go new file mode 100644 index 0000000000..c77dc209a6 --- /dev/null +++ b/event/eventlog_test.go @@ -0,0 +1,38 @@ +package event_test + +import ( + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/pgeventstorage" + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/stretchr/testify/require" + "golang.org/x/net/context" +) + +func TestStoreEvent(t *testing.T) { + ctx := context.Background() + + eventDBCfg := dbutils.NewEventConfigFromEnv() + eventStorage, err := pgeventstorage.NewPostgresEventStorage(eventDBCfg) + require.NoError(t, err) + + ev := &event.Event{ + ReceivedAt: time.Now(), + IPAddress: "127.0.0.1", + Source: event.Source_Node, + Component: event.Component_Sequencer, + Level: event.Level_Error, + EventID: event.EventID_ExecutorError, + Description: "This is a test event", + Data: []byte("This is a test event"), + Json: eventDBCfg, + } + + eventLog := event.NewEventLog(event.Config{}, eventStorage) + defer eventStorage.Close() //nolint:gosec,errcheck + + err = eventLog.LogEvent(ctx, ev) + require.NoError(t, err) +} diff --git a/event/interfaces.go b/event/interfaces.go new file mode 100644 index 0000000000..5dd0efef26 --- /dev/null +++ b/event/interfaces.go @@ -0,0 +1,11 @@ +package event + +import ( + "context" +) + +// Storage is the interface for the event storage +type Storage interface { + // LogEvent logs an event + LogEvent(ctx context.Context, event *Event) error +} diff --git a/event/nileventstorage/nileventstorage.go b/event/nileventstorage/nileventstorage.go new file mode 100644 index 0000000000..0fa6558132 --- /dev/null +++ b/event/nileventstorage/nileventstorage.go @@ -0,0 +1,38 @@ +package nileventstorage + +import ( + "context" + + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/log" +) + +// NilEventStorage is an implementation of the event storage interface +// that just logs but does not store the data +type NilEventStorage struct { +} + +// NewNilEventStorage creates and initializes an instance of NewNilEventStorage +func NewNilEventStorage() (*NilEventStorage, error) { + return &NilEventStorage{}, nil +} + +// LogEvent logs an event following the defined interface +func (p *NilEventStorage) LogEvent(ctx context.Context, ev *event.Event) error { + LogEvent(ev) + return nil +} + +// LogEvent actually logs the event +func LogEvent(ev *event.Event) { + switch ev.Level { + case event.Level_Emergency, event.Level_Alert, event.Level_Critical, event.Level_Error: + log.Errorf("Event: %+v", ev) + case event.Level_Warning, event.Level_Notice: + log.Warnf("Event: %+v", ev) + case event.Level_Info: + log.Infof("Event: %+v", ev) + case event.Level_Debug: + log.Debugf("Event: %+v", ev) + } +} diff --git a/event/pgeventstorage/pgeventstorage.go b/event/pgeventstorage/pgeventstorage.go new file mode 100644 index 0000000000..93839524fb --- /dev/null +++ b/event/pgeventstorage/pgeventstorage.go @@ -0,0 +1,48 @@ +package pgeventstorage + +import ( + "context" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/jackc/pgx/v4/pgxpool" +) + +// PostgresEventStorage is an implementation of the event storage interface +// that uses a postgres database to store the data +type PostgresEventStorage struct { + db *pgxpool.Pool +} + +// NewPostgresEventStorage creates and initializes an instance of PostgresEventStorage +func NewPostgresEventStorage(cfg db.Config) (*PostgresEventStorage, error) { + poolDB, err := db.NewSQLDB(cfg) + if err != nil { + return nil, err + } + + return &PostgresEventStorage{ + db: poolDB, + }, nil +} + +// Close closes the database connection +func (p *PostgresEventStorage) Close() error { + p.db.Close() + return nil +} + +// LogEvent logs an event to the database +func (p *PostgresEventStorage) LogEvent(ctx context.Context, ev *event.Event) error { + const insertEventSQL = "INSERT INTO event (received_at, ip_address, source, component, level, event_id, description, data, json) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)" + + var ipAddressPtr *string + if ev.IPAddress != "" { + ipAddressPtr = &ev.IPAddress + } + + nileventstorage.LogEvent(ev) + _, err := p.db.Exec(ctx, insertEventSQL, ev.ReceivedAt, ipAddressPtr, ev.Source, ev.Component, ev.Level, ev.EventID, ev.Description, ev.Data, ev.Json) + return err +} diff --git a/gasprice/allbatches.go b/gasprice/allbatches.go deleted file mode 100644 index a629c0f0ca..0000000000 --- a/gasprice/allbatches.go +++ /dev/null @@ -1,43 +0,0 @@ -package gasprice - -import ( - "context" - "math/big" - "sync" -) - -// AllBatches struct for all batches avg price strategy. -type AllBatches struct { - // Average gas price (rolling average) - averageGasPrice *big.Int // The average gas price that gets queried - averageGasPriceCount *big.Int // Param used in the avg. gas price calculation - - agpMux sync.Mutex // Mutex for the averageGasPrice calculation -} - -// NewEstimatorAllBatches init gas price estimator for all batches strategy. -func NewEstimatorAllBatches() *AllBatches { - return &AllBatches{ - averageGasPrice: big.NewInt(0), - averageGasPriceCount: big.NewInt(0), - } -} - -// UpdateGasPriceAvg Updates the rolling average value of the gas price. -func (g *AllBatches) UpdateGasPriceAvg(newValue *big.Int) { - g.agpMux.Lock() - - g.averageGasPriceCount.Add(g.averageGasPriceCount, big.NewInt(1)) - - differential := big.NewInt(0) - differential.Div(newValue.Sub(newValue, g.averageGasPrice), g.averageGasPriceCount) - - g.averageGasPrice.Add(g.averageGasPrice, differential) - - g.agpMux.Unlock() -} - -// GetAvgGasPrice get avg gas price from all blocks. -func (g *AllBatches) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { - return g.averageGasPrice, nil -} diff --git a/gasprice/config.go b/gasprice/config.go index 8eb3dabd3e..4ab42d277e 100644 --- a/gasprice/config.go +++ b/gasprice/config.go @@ -2,6 +2,8 @@ package gasprice import ( "math/big" + + "github.com/0xPolygonHermez/zkevm-node/config/types" ) // EstimatorType different gas estimator types. @@ -10,19 +12,21 @@ type EstimatorType string const ( // DefaultType default gas price from config is set. DefaultType EstimatorType = "default" - // AllBatchesType calculate average gas used from all batches. - AllBatchesType EstimatorType = "allbatches" // LastNBatchesType calculate average gas tip from last n batches. LastNBatchesType EstimatorType = "lastnbatches" + // FollowerType calculate the gas price basing on the L1 gasPrice. + FollowerType EstimatorType = "follower" ) // Config for gas price estimator. type Config struct { Type EstimatorType `mapstructure:"Type"` - DefaultGasPriceWei uint64 `mapstructure:"DefaultGasPriceWei"` - MaxPrice *big.Int `mapstructure:"MaxPrice"` - IgnorePrice *big.Int `mapstructure:"IgnorePrice"` - CheckBlocks int `mapstructure:"CheckBlocks"` - Percentile int `mapstructure:"Percentile"` + DefaultGasPriceWei uint64 `mapstructure:"DefaultGasPriceWei"` + MaxPrice *big.Int `mapstructure:"MaxPrice"` + IgnorePrice *big.Int `mapstructure:"IgnorePrice"` + CheckBlocks int `mapstructure:"CheckBlocks"` + Percentile int `mapstructure:"Percentile"` + UpdatePeriod types.Duration `mapstructure:"UpdatePeriod"` + Factor float64 `mapstructure:"Factor"` } diff --git a/gasprice/default.go b/gasprice/default.go index 3cbdbce977..76797ac1e3 100644 --- a/gasprice/default.go +++ b/gasprice/default.go @@ -2,44 +2,29 @@ package gasprice import ( "context" - "errors" "fmt" - "math/big" - - "github.com/0xPolygonHermez/zkevm-node/state" ) -// Default gas price from config is set. -type Default struct { +// DefaultGasPricer gas price from config is set. +type DefaultGasPricer struct { cfg Config pool pool + ctx context.Context } -// GetAvgGasPrice get default gas price from the pool. -func (d *Default) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { - gasPrice, err := d.pool.GetGasPrice(ctx) - if errors.Is(err, state.ErrNotFound) { - return big.NewInt(0), nil - } else if err != nil { - return nil, err - } - return new(big.Int).SetUint64(gasPrice), nil +// newDefaultGasPriceSuggester init default gas price suggester. +func newDefaultGasPriceSuggester(ctx context.Context, cfg Config, pool pool) *DefaultGasPricer { + gpe := &DefaultGasPricer{ctx: ctx, cfg: cfg, pool: pool} + gpe.setDefaultGasPrice() + return gpe } // UpdateGasPriceAvg not needed for default strategy. -func (d *Default) UpdateGasPriceAvg(newValue *big.Int) {} +func (d *DefaultGasPricer) UpdateGasPriceAvg() {} -func (d *Default) setDefaultGasPrice() { - ctx := context.Background() - err := d.pool.SetGasPrice(ctx, d.cfg.DefaultGasPriceWei) +func (d *DefaultGasPricer) setDefaultGasPrice() { + err := d.pool.SetGasPrice(d.ctx, d.cfg.DefaultGasPriceWei) if err != nil { panic(fmt.Errorf("failed to set default gas price, err: %v", err)) } } - -// NewDefaultEstimator init default gas price estimator. -func NewDefaultEstimator(cfg Config, pool pool) *Default { - gpe := &Default{cfg: cfg, pool: pool} - gpe.setDefaultGasPrice() - return gpe -} diff --git a/gasprice/default_test.go b/gasprice/default_test.go new file mode 100644 index 0000000000..7a2622ebd8 --- /dev/null +++ b/gasprice/default_test.go @@ -0,0 +1,27 @@ +package gasprice + +import ( + "context" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/log" +) + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stdout"}, + }) +} + +func TestUpdateGasPriceDefault(t *testing.T) { + ctx := context.Background() + cfg := Config{ + Type: DefaultType, + DefaultGasPriceWei: 1000000000, + } + poolM := new(poolMock) + poolM.On("SetGasPrice", ctx, cfg.DefaultGasPriceWei).Return(nil).Once() + dge := newDefaultGasPriceSuggester(ctx, cfg, poolM) + dge.UpdateGasPriceAvg() +} diff --git a/gasprice/follower.go b/gasprice/follower.go new file mode 100644 index 0000000000..adfc4784a8 --- /dev/null +++ b/gasprice/follower.go @@ -0,0 +1,77 @@ +package gasprice + +import ( + "context" + "fmt" + "math/big" + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/log" +) + +// FollowerGasPrice struct. +type FollowerGasPrice struct { + cfg Config + pool pool + ctx context.Context + eth ethermanInterface +} + +// newFollowerGasPriceSuggester inits l2 follower gas price suggester which is based on the l1 gas price. +func newFollowerGasPriceSuggester(ctx context.Context, cfg Config, pool pool, ethMan ethermanInterface) *FollowerGasPrice { + gps := &FollowerGasPrice{ + cfg: cfg, + pool: pool, + ctx: ctx, + eth: ethMan, + } + gps.UpdateGasPriceAvg() + return gps +} + +// UpdateGasPriceAvg updates the gas price. +func (f *FollowerGasPrice) UpdateGasPriceAvg() { + ctx := context.Background() + // Get L1 gasprice + gp := f.eth.GetL1GasPrice(f.ctx) + if big.NewInt(0).Cmp(gp) == 0 { + log.Warn("gas price 0 received. Skipping update...") + return + } + // Apply factor to calculate l2 gasPrice + factor := big.NewFloat(0).SetFloat64(f.cfg.Factor) + res := new(big.Float).Mul(factor, big.NewFloat(0).SetInt(gp)) + + // Store l2 gasPrice calculated + result := new(big.Int) + res.Int(result) + minGasPrice := big.NewInt(0).SetUint64(f.cfg.DefaultGasPriceWei) + if minGasPrice.Cmp(result) == 1 { // minGasPrice > result + log.Warn("setting minGasPrice for L2") + result = minGasPrice + } + var truncateValue *big.Int + log.Debug("Full L2 gas price value: ", result, ". Length: ", len(result.String())) + numLength := len(result.String()) + if numLength > 3 { //nolint:gomnd + aux := "%0" + strconv.Itoa(numLength-3) + "d" //nolint:gomnd + var ok bool + value := result.String()[:3] + fmt.Sprintf(aux, 0) + truncateValue, ok = new(big.Int).SetString(value, encoding.Base10) + if !ok { + log.Error("error converting: ", truncateValue) + } + } else { + truncateValue = result + } + log.Debug("Storing truncated L2 gas price: ", truncateValue) + if truncateValue != nil { + err := f.pool.SetGasPrice(ctx, truncateValue.Uint64()) + if err != nil { + log.Errorf("failed to update gas price in poolDB, err: %v", err) + } + } else { + log.Error("nil value detected. Skipping...") + } +} diff --git a/gasprice/follower_test.go b/gasprice/follower_test.go new file mode 100644 index 0000000000..206f3ec9b0 --- /dev/null +++ b/gasprice/follower_test.go @@ -0,0 +1,39 @@ +package gasprice + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/log" +) + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stdout"}, + }) +} + +func TestUpdateGasPriceFollower(t *testing.T) { + ctx := context.Background() + var d time.Duration = 1000000000 + + cfg := Config{ + Type: FollowerType, + DefaultGasPriceWei: 1000000000, + UpdatePeriod: types.NewDuration(d), + Factor: 0.5, + } + poolM := new(poolMock) + ethM := new(ethermanMock) + ethM.On("GetL1GasPrice", ctx).Return(big.NewInt(10000000000)).Once() + poolM.On("SetGasPrice", ctx, uint64(5000000000)).Return(nil).Once() + f := newFollowerGasPriceSuggester(ctx, cfg, poolM, ethM) + + ethM.On("GetL1GasPrice", ctx).Return(big.NewInt(10000000000)).Once() + poolM.On("SetGasPrice", ctx, uint64(5000000000)).Return(nil).Once() + f.UpdateGasPriceAvg() +} diff --git a/gasprice/gaspricesuggester.go b/gasprice/gaspricesuggester.go new file mode 100644 index 0000000000..63aebe7860 --- /dev/null +++ b/gasprice/gaspricesuggester.go @@ -0,0 +1,43 @@ +package gasprice + +import ( + "context" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" +) + +// L2GasPricer interface for gas price suggester. +type L2GasPricer interface { + UpdateGasPriceAvg() +} + +// NewL2GasPriceSuggester init. +func NewL2GasPriceSuggester(ctx context.Context, cfg Config, pool pool, ethMan *etherman.Client, state *state.State) { + var gpricer L2GasPricer + switch cfg.Type { + case LastNBatchesType: + log.Info("Lastnbatches type selected") + gpricer = newLastNL2BlocksGasPriceSuggester(ctx, cfg, state, pool) + case FollowerType: + log.Info("Follower type selected") + gpricer = newFollowerGasPriceSuggester(ctx, cfg, pool, ethMan) + case DefaultType: + log.Info("Default type selected") + gpricer = newDefaultGasPriceSuggester(ctx, cfg, pool) + default: + log.Fatal("unknown l2 gas price suggester type ", cfg.Type, ". Please specify a valid one: 'lastnbatches', 'follower' or 'default'") + } + + for { + select { + case <-ctx.Done(): + log.Info("Finishing l2 gas price suggester...") + return + case <-time.After(cfg.UpdatePeriod.Duration): + gpricer.UpdateGasPriceAvg() + } + } +} diff --git a/gasprice/interfaces.go b/gasprice/interfaces.go index 30fd5963f3..5fc87edf71 100644 --- a/gasprice/interfaces.go +++ b/gasprice/interfaces.go @@ -2,6 +2,7 @@ package gasprice import ( "context" + "math/big" "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" @@ -20,3 +21,8 @@ type stateInterface interface { GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) GetTxsByBlockNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) ([]*types.Transaction, error) } + +// ethermanInterface contains the methods required to interact with ethereum. +type ethermanInterface interface { + GetL1GasPrice(ctx context.Context) *big.Int +} diff --git a/gasprice/lastnbatches.go b/gasprice/lastnbatches.go index d8901e3c58..80346afdde 100644 --- a/gasprice/lastnbatches.go +++ b/gasprice/lastnbatches.go @@ -2,49 +2,52 @@ package gasprice import ( "context" - "fmt" "math/big" "sort" "sync" + + "github.com/0xPolygonHermez/zkevm-node/log" ) const sampleNumber = 3 // Number of transactions sampled in a batch. -// LastNL2Blocks struct for gas price estimator last n l2 blocks. -type LastNL2Blocks struct { +// LastNL2BlocksGasPrice struct for gas price estimator last n l2 blocks. +type LastNL2BlocksGasPrice struct { lastL2BlockNumber uint64 lastPrice *big.Int cfg Config + ctx context.Context cacheLock sync.RWMutex fetchLock sync.Mutex state stateInterface + pool pool } -// UpdateGasPriceAvg for last n bathes strategy is not needed to implement this function. -func (g *LastNL2Blocks) UpdateGasPriceAvg(newValue *big.Int) {} - -// NewEstimatorLastNL2Blocks init gas price estimator for last n l2 blocks strategy. -func NewEstimatorLastNL2Blocks(cfg Config, state stateInterface) *LastNL2Blocks { - return &LastNL2Blocks{ +// newLastNL2BlocksGasPriceSuggester init gas price suggester for last n l2 blocks strategy. +func newLastNL2BlocksGasPriceSuggester(ctx context.Context, cfg Config, state stateInterface, pool pool) *LastNL2BlocksGasPrice { + return &LastNL2BlocksGasPrice{ cfg: cfg, + ctx: ctx, state: state, + pool: pool, } } -// GetAvgGasPrice calculate avg gas price from last n l2 blocks. -func (g *LastNL2Blocks) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { - l2BlockNumber, err := g.state.GetLastL2BlockNumber(ctx, nil) +// UpdateGasPriceAvg for last n bathes strategy is not needed to implement this function. +func (g *LastNL2BlocksGasPrice) UpdateGasPriceAvg() { + l2BlockNumber, err := g.state.GetLastL2BlockNumber(g.ctx, nil) if err != nil { - return nil, fmt.Errorf("failed to get last l2 block number, err: %v", err) + log.Errorf("failed to get last l2 block number, err: %v", err) } g.cacheLock.RLock() lastL2BlockNumber, lastPrice := g.lastL2BlockNumber, g.lastPrice g.cacheLock.RUnlock() if l2BlockNumber == lastL2BlockNumber { - return lastPrice, nil + log.Debug("Block is still the same, no need to update the gas price at the moment") + return } g.fetchLock.Lock() @@ -59,7 +62,7 @@ func (g *LastNL2Blocks) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { ) for sent < g.cfg.CheckBlocks && number > 0 { - go g.getL2BlockTxsTips(ctx, number, sampleNumber, g.cfg.IgnorePrice, result, quit) + go g.getL2BlockTxsTips(g.ctx, number, sampleNumber, g.cfg.IgnorePrice, result, quit) sent++ exp++ number-- @@ -69,7 +72,7 @@ func (g *LastNL2Blocks) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { res := <-result if res.err != nil { close(quit) - return lastPrice, res.err + return } exp-- @@ -93,11 +96,15 @@ func (g *LastNL2Blocks) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { g.lastL2BlockNumber = l2BlockNumber g.cacheLock.Unlock() - return price, nil + // Store gasPrice + err = g.pool.SetGasPrice(g.ctx, g.lastPrice.Uint64()) + if err != nil { + log.Errorf("failed to update gas price in poolDB, err: %v", err) + } } // getL2BlockTxsTips calculates l2 block transaction gas fees. -func (g *LastNL2Blocks) getL2BlockTxsTips(ctx context.Context, l2BlockNumber uint64, limit int, ignorePrice *big.Int, result chan results, quit chan struct{}) { +func (g *LastNL2BlocksGasPrice) getL2BlockTxsTips(ctx context.Context, l2BlockNumber uint64, limit int, ignorePrice *big.Int, result chan results, quit chan struct{}) { txs, err := g.state.GetTxsByBlockNumber(ctx, l2BlockNumber, nil) if txs == nil { select { diff --git a/gasprice/mock_etherman.go b/gasprice/mock_etherman.go new file mode 100644 index 0000000000..488c86f58a --- /dev/null +++ b/gasprice/mock_etherman.go @@ -0,0 +1,46 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package gasprice + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// ethermanMock is an autogenerated mock type for the ethermanInterface type +type ethermanMock struct { + mock.Mock +} + +// GetL1GasPrice provides a mock function with given fields: ctx +func (_m *ethermanMock) GetL1GasPrice(ctx context.Context) *big.Int { + ret := _m.Called(ctx) + + var r0 *big.Int + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + return r0 +} + +type mockConstructorTestingTnewEthermanMock interface { + mock.TestingT + Cleanup(func()) +} + +// newEthermanMock creates a new instance of ethermanMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newEthermanMock(t mockConstructorTestingTnewEthermanMock) *ethermanMock { + mock := ðermanMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/gasprice/mock_pool.go b/gasprice/mock_pool.go new file mode 100644 index 0000000000..7379f7c1a0 --- /dev/null +++ b/gasprice/mock_pool.go @@ -0,0 +1,67 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package gasprice + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// poolMock is an autogenerated mock type for the pool type +type poolMock struct { + mock.Mock +} + +// GetGasPrice provides a mock function with given fields: ctx +func (_m *poolMock) GetGasPrice(ctx context.Context) (uint64, error) { + ret := _m.Called(ctx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SetGasPrice provides a mock function with given fields: ctx, gasPrice +func (_m *poolMock) SetGasPrice(ctx context.Context, gasPrice uint64) error { + ret := _m.Called(ctx, gasPrice) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) error); ok { + r0 = rf(ctx, gasPrice) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTnewPoolMock interface { + mock.TestingT + Cleanup(func()) +} + +// newPoolMock creates a new instance of poolMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newPoolMock(t mockConstructorTestingTnewPoolMock) *poolMock { + mock := &poolMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/go.mod b/go.mod index fb926d65dc..2758955a5f 100644 --- a/go.mod +++ b/go.mod @@ -1,126 +1,146 @@ module github.com/0xPolygonHermez/zkevm-node -go 1.17 +go 1.19 require ( github.com/didip/tollbooth/v6 v6.1.2 - github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf - github.com/ethereum/go-ethereum v1.10.25 - github.com/go-git/go-billy/v5 v5.3.1 - github.com/go-git/go-git/v5 v5.4.2 + github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 + github.com/ethereum/go-ethereum v1.11.5 + github.com/go-git/go-billy/v5 v5.4.1 + github.com/go-git/go-git/v5 v5.7.0 github.com/gobuffalo/packr/v2 v2.8.3 + github.com/google/uuid v1.3.0 github.com/hermeznetwork/tracerr v0.3.2 - github.com/iden3/go-iden3-crypto v0.0.14-0.20220413123345-edc36bfa5247 - github.com/imdario/mergo v0.3.13 - github.com/jackc/pgconn v1.13.0 - github.com/jackc/pgx/v4 v4.17.1 + github.com/iden3/go-iden3-crypto v0.0.15 + github.com/jackc/pgconn v1.14.0 + github.com/jackc/pgx/v4 v4.18.1 github.com/mitchellh/mapstructure v1.5.0 - github.com/rubenv/sql-migrate v0.0.0-20211023115951-9f02b1e13857 - github.com/spf13/afero v1.9.2 - github.com/spf13/viper v1.13.0 - github.com/stretchr/testify v1.8.0 + github.com/prometheus/client_model v0.4.0 + github.com/prometheus/common v0.44.0 + github.com/rubenv/sql-migrate v1.4.0 + github.com/spf13/afero v1.9.5 + github.com/spf13/viper v1.15.0 + github.com/stretchr/testify v1.8.3 github.com/umbracle/ethgo v0.1.3 - github.com/urfave/cli/v2 v2.16.3 - go.uber.org/zap v1.23.0 - golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa - golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 - google.golang.org/grpc v1.49.0 - google.golang.org/protobuf v1.28.1 + github.com/urfave/cli/v2 v2.25.3 + go.uber.org/zap v1.24.0 + golang.org/x/crypto v0.9.0 + golang.org/x/net v0.10.0 + golang.org/x/sync v0.2.0 + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/jackc/pgtype v1.12.0 // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect -) - -require ( - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect + github.com/DataDog/zstd v1.5.2 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // 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/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-kit/kit v0.9.0 // indirect - github.com/go-ole/go-ole v1.2.1 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-pkgz/expirable-cache v0.0.3 // indirect - github.com/go-stack/stack v1.8.0 // indirect - github.com/gobuffalo/logger v1.0.6 // indirect - github.com/gobuffalo/packd v1.0.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gobuffalo/logger v1.0.7 // indirect + github.com/gobuffalo/packd v1.0.2 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.4.2 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.1 + github.com/huin/goupnp v1.0.3 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/puddle v1.3.0 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/karrick/godirwalk v1.16.1 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/karrick/godirwalk v1.17.0 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/klauspost/compress v1.15.15 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect - github.com/magiconair/properties v1.8.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/markbates/errx v1.1.0 // indirect github.com/markbates/oncer v1.0.0 // indirect github.com/markbates/safe v1.0.1 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pjbgf/sha1cd v0.3.0 // 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/prometheus/procfs v0.9.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sergi/go-diff v1.1.0 // indirect + github.com/sergi/go-diff v1.2.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/skeema/knownhosts v1.1.1 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.4.0 // indirect - github.com/subosito/gotenv v1.4.1 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect - github.com/tklauser/go-sysconf v0.3.5 // indirect - github.com/tklauser/numcpus v0.2.2 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // 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-20210220033141-f8bda1e9f3ba // indirect - google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect - gopkg.in/gorp.v1 v1.7.2 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/subosito/gotenv v1.4.2 // 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/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect + github.com/valyala/fastjson v1.4.1 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.8.0 // indirect + golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.1.0 // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) require ( - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/lib/pq v1.10.7 // indirect - github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect - github.com/valyala/fastjson v1.4.1 // indirect - github.com/ziutek/mymysql v1.5.4 // indirect - go.uber.org/atomic v1.9.0 // indirect + github.com/gorilla/websocket v1.5.0 + github.com/holiman/uint256 v1.2.2 + github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect +) + +require ( + github.com/imdario/mergo v0.3.15 // indirect + github.com/prometheus/client_golang v1.15.1 ) diff --git a/go.sum b/go.sum index 5bba71e85b..1f2484cc99 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,12 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= 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.44.3/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= @@ -23,31 +20,15 @@ cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPT cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= 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/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= 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= @@ -58,284 +39,242 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl 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= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 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/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= +github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= +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/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -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/a8m/expect v1.0.0/go.mod h1:4IwSCMumY49ScypDnjNbYEjgVeqy1/U2cEs3Lat96eA= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= 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 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/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 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/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-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -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/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= 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/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -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.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= -github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= -github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= 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= -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/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= 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/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -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/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b h1:pik3LX++5O3UiNWv45wfP/WT81l7ukBJzd3uUiifbSU= -github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/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 v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= -github.com/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/dchest/blake512 v1.0.0/go.mod h1:FV1x7xPPLWukZlpDpWQ88rF/SFwZ5qbskrzhLMB92JI= -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/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= 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/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= 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/didip/tollbooth/v6 v6.1.2 h1:Kdqxmqw9YTv0uKajBUiWQg+GURL/k4vy9gmLCL01PjQ= github.com/didip/tollbooth/v6 v6.1.2/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= 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.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 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-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= -github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY= +github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs= 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/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= 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/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= 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.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.25 h1:5dFrKJDnYf8L6/5o42abCE6a9yJm9cs4EJVRyYMr55s= -github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +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/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= +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/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= 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/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +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/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/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/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-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= +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= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE= +github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8= 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-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= +github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= 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/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 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-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +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-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6dksJLXQDc= github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= 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-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 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/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM= -github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= -github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI= -github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/logger v1.0.7 h1:LTLwWelETXDYyqF/ASf0nxaIcdEOIJNxRokPcfI/xbU= +github.com/gobuffalo/logger v1.0.7/go.mod h1:u40u6Bq3VVvaMcy5sRBclD8SXhBYPS0Qk95ubt+1xJM= github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= -github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg= +github.com/gobuffalo/packd v1.0.2 h1:Yg523YqnOxGIWCp69W12yYBKsoChwI7mtu6ceM9Bwfw= +github.com/gobuffalo/packd v1.0.2/go.mod h1:sUc61tDqGMXON80zpKGp92lDb86Km28jfvX7IAyxFT8= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= +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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +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/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 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-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -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-20190129154638-5b532d6fd5ef/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/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/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= @@ -345,7 +284,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt 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.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -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= @@ -362,16 +300,15 @@ 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/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -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/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 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= @@ -383,18 +320,15 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/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/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 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= @@ -408,107 +342,78 @@ github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= 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.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 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/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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/grpc-ecosystem/go-grpc-middleware v1.0.0/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.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1/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-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 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 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 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/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hermeznetwork/tracerr v0.3.2 h1:QB3TlQxO/4XHyixsg+nRZPuoel/FFQlQ7oAoHDD5l1c= github.com/hermeznetwork/tracerr v0.3.2/go.mod h1:nsWC1+tc4qUEbUGRv4DcPJJTjLsedlPajlFmpJoohK4= 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/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/holiman/uint256 v1.2.1 h1:XRtyuda/zw2l+Bq/38n5XUoEF72aSOu/77Thd9pPp2o= -github.com/holiman/uint256 v1.2.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= +github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 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/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/iden3/go-iden3-crypto v0.0.14-0.20220413123345-edc36bfa5247 h1:9i4N178PRIcROyIsnHbMxINrwPkN/czg7TI2izUQDc8= -github.com/iden3/go-iden3-crypto v0.0.14-0.20220413123345-edc36bfa5247/go.mod h1:swXIv0HFbJKobbQBtsB50G7IHr6PbTowutSew/iBEoo= +github.com/iden3/go-iden3-crypto v0.0.15 h1:4MJYlrot1l31Fzlo2sF56u7EVFeHHJkxGXXZCtESgK4= +github.com/iden3/go-iden3-crypto v0.0.15/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= 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/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -519,8 +424,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= -github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -529,7 +434,6 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -537,22 +441,23 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= -github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= -github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.17.1 h1:tASdE79tX9LOQu3MMvioWT6YaZkf58ZhmLHhV4sv5WM= -github.com/jackc/pgx/v4 v4.17.1/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= +github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -562,73 +467,55 @@ 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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -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/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -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/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= 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.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/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= -github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI= +github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= +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/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.0/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/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +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 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -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.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -636,10 +523,8 @@ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSD github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= @@ -648,47 +533,44 @@ github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -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.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/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-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.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.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.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 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-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= -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.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/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/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 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= @@ -696,23 +578,23 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu 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/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/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/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 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/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -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/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= 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/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/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= +github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -721,163 +603,139 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn 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.1/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/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -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.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/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -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/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= -github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -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/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/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/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -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/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= +github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= +github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= 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/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.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.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -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.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -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/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/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 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 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/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 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/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rubenv/sql-migrate v0.0.0-20211023115951-9f02b1e13857 h1:nI2V0EI64bEYpbyOmwYfk0DYu26j0k4LhC7YS4tKkhA= -github.com/rubenv/sql-migrate v0.0.0-20211023115951-9f02b1e13857/go.mod h1:HFLT6i9iR4QBOF5rdCyjddC9t59ArqWJV2xx+jwcCMo= +github.com/rubenv/sql-migrate v1.4.0 h1:y4ndB3hq5tmjvQ8jcuqhLgeEqoxIjEidN5RaCkKOAAE= +github.com/rubenv/sql-migrate v1.4.0/go.mod h1:lRxHt4vTgRJtpGbulUUYHA9dzfbBJXRt+PwUF/jeNYo= +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/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/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/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE= +github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= 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/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/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -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/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= -github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= -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/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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= @@ -886,68 +744,65 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -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/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.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-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -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/umbracle/ethgo v0.1.3 h1:s8D7Rmphnt71zuqrgsGTMS5gTNbueGO1zKLh7qsFzTM= github.com/umbracle/ethgo v0.1.3/go.mod h1:g9zclCLixH8liBI27Py82klDkW7Oo33AxUOr+M9lzrU= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E= github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= -github.com/urfave/cli/v2 v2.16.3 h1:gHoFIwpPjoyIMbJp/VFd+/vuD0dAgFK4B6DpEMFJfQk= -github.com/urfave/cli/v2 v2.16.3/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= +github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= 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/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +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/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +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/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= 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= @@ -955,7 +810,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -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= @@ -964,36 +818,32 @@ 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.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/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 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.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.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= -go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 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-20190219172222-a4c6cb3142f2/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-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -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-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -1003,15 +853,15 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/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/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= 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= @@ -1021,8 +871,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= 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= @@ -1048,13 +898,11 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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-20180911220305-26e67e76b6c3/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= @@ -1062,17 +910,17 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r 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-20190327091125-710a502c58a2/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-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 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-20190923162816-aa69164e4478/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= @@ -1087,35 +935,29 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 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-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/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-20211015210444-4f30a5c0130f/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/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1128,15 +970,6 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 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= @@ -1148,8 +981,10 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/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= @@ -1157,6 +992,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h 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-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= @@ -1167,25 +1003,20 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/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-20191008105621-543471e840be/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-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= @@ -1195,13 +1026,8 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200905004654-be1d3432aa8f/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= @@ -1212,47 +1038,47 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/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-20210320140829-1e4c9ba3b0c4/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-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/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-20210514084401-e8d321eab015/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-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/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-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1261,25 +1087,29 @@ 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/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-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-20200416051211-89c76fbcd5d1/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.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/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-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= 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-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1290,7 +1120,6 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/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= @@ -1300,12 +1129,10 @@ 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= 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= @@ -1315,8 +1142,8 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK 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-20200308013534-11ec41452d41/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-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 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= @@ -1335,27 +1162,18 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -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= @@ -1378,24 +1196,6 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= 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= @@ -1403,12 +1203,12 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww 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/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 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= @@ -1416,7 +1216,6 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= @@ -1447,43 +1246,11 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I= -google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1504,20 +1271,9 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= 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= @@ -1530,27 +1286,24 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj 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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/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/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= -gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -1563,17 +1316,16 @@ 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-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -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= @@ -1581,9 +1333,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/hex/hex.go b/hex/hex.go index ab224ddc7f..d6a1468f17 100644 --- a/hex/hex.go +++ b/hex/hex.go @@ -11,16 +11,9 @@ import ( const ( // Base represents the hexadecimal base, which is 16 Base = 16 -) -// TODO Remove -var ( - ErrSyntax = &DecError{"invalid hex string"} - ErrMissingPrefix = &DecError{"hex string without 0x prefix"} - ErrEmptyNumber = &DecError{"hex string \"0x\""} - ErrLeadingZero = &DecError{"hex number with leading zero digits"} - ErrUint64Range = &DecError{"hex number > 64 bits"} - ErrBig256Range = &DecError{"hex number > 256 bits"} + // BitSize64 64 bits + BitSize64 = 64 ) // DecError represents an error when decoding a hex value @@ -60,6 +53,12 @@ func MustDecodeHex(str string) []byte { return buf } +// DecodeUint64 type-checks and converts a hex string to a uint64 +func DecodeUint64(str string) uint64 { + i := DecodeBig(str) + return i.Uint64() +} + // EncodeUint64 encodes a number as a hex string with 0x prefix. func EncodeUint64(i uint64) string { enc := make([]byte, 2, 10) //nolint:gomnd @@ -95,10 +94,22 @@ func EncodeBig(bigint *big.Int) string { return fmt.Sprintf("%#x", bigint) } -// DecodeHexToBig converts a hex number to a big.Int value -func DecodeHexToBig(hexNum string) *big.Int { +// DecodeBig converts a hex number to a big.Int value +func DecodeBig(hexNum string) *big.Int { + str := strings.TrimPrefix(hexNum, "0x") createdNum := new(big.Int) - createdNum.SetString(hexNum, Base) + createdNum.SetString(str, Base) return createdNum } + +// IsValid checks if the provided string is a valid hexadecimal value +func IsValid(s string) bool { + str := strings.TrimPrefix(s, "0x") + for _, b := range []byte(str) { + if !(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') { + return false + } + } + return true +} diff --git a/hex/hex_test.go b/hex/hex_test.go new file mode 100644 index 0000000000..12e6e44048 --- /dev/null +++ b/hex/hex_test.go @@ -0,0 +1,16 @@ +package hex + +import ( + "math" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEncodeDecodeBig(t *testing.T) { + b := big.NewInt(math.MaxInt64) + e := EncodeBig(b) + d := DecodeBig(e) + assert.Equal(t, b.Uint64(), d.Uint64()) +} diff --git a/jsonrpc/client.go b/jsonrpc/client/client.go similarity index 60% rename from jsonrpc/client.go rename to jsonrpc/client/client.go index fee17aaefc..7ae0057713 100644 --- a/jsonrpc/client.go +++ b/jsonrpc/client/client.go @@ -1,4 +1,4 @@ -package jsonrpc +package client import ( "bytes" @@ -6,20 +6,34 @@ import ( "fmt" "io" "net/http" + + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" ) +// Client defines typed wrappers for the zkEVM RPC API. +type Client struct { + url string +} + +// NewClient creates an instance of client +func NewClient(url string) *Client { + return &Client{ + url: url, + } +} + // JSONRPCCall executes a 2.0 JSON RPC HTTP Post Request to the provided URL with // the provided method and parameters, which is compatible with the Ethereum // JSON RPC Server. -func JSONRPCCall(url, method string, parameters ...interface{}) (Response, error) { +func JSONRPCCall(url, method string, parameters ...interface{}) (types.Response, error) { const jsonRPCVersion = "2.0" params, err := json.Marshal(parameters) if err != nil { - return Response{}, err + return types.Response{}, err } - req := Request{ + req := types.Request{ JSONRPC: jsonRPCVersion, ID: float64(1), Method: method, @@ -28,36 +42,36 @@ func JSONRPCCall(url, method string, parameters ...interface{}) (Response, error reqBody, err := json.Marshal(req) if err != nil { - return Response{}, err + return types.Response{}, err } reqBodyReader := bytes.NewReader(reqBody) httpReq, err := http.NewRequest(http.MethodPost, url, reqBodyReader) if err != nil { - return Response{}, err + return types.Response{}, err } httpReq.Header.Add("Content-type", "application/json") httpRes, err := http.DefaultClient.Do(httpReq) if err != nil { - return Response{}, err + return types.Response{}, err } if httpRes.StatusCode != http.StatusOK { - return Response{}, fmt.Errorf("Invalid status code, expected: %v, found: %v", http.StatusOK, httpRes.StatusCode) + return types.Response{}, fmt.Errorf("Invalid status code, expected: %v, found: %v", http.StatusOK, httpRes.StatusCode) } resBody, err := io.ReadAll(httpRes.Body) if err != nil { - return Response{}, err + return types.Response{}, err } defer httpRes.Body.Close() - var res Response + var res types.Response err = json.Unmarshal(resBody, &res) if err != nil { - return Response{}, err + return types.Response{}, err } return res, nil diff --git a/jsonrpc/client/zkevm.go b/jsonrpc/client/zkevm.go new file mode 100644 index 0000000000..f2e78aa4af --- /dev/null +++ b/jsonrpc/client/zkevm.go @@ -0,0 +1,55 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" +) + +// BatchNumber returns the latest batch number +func (c *Client) BatchNumber(ctx context.Context) (uint64, error) { + response, err := JSONRPCCall(c.url, "zkevm_batchNumber") + if err != nil { + return 0, err + } + + if response.Error != nil { + return 0, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result string + err = json.Unmarshal(response.Result, &result) + if err != nil { + return 0, err + } + + bigBatchNumber := hex.DecodeBig(result) + batchNumber := bigBatchNumber.Uint64() + + return batchNumber, nil +} + +// BatchByNumber returns a batch from the current canonical chain. If number is nil, the +// latest known batch is returned. +func (c *Client) BatchByNumber(ctx context.Context, number *big.Int) (*types.Batch, error) { + response, err := JSONRPCCall(c.url, "zkevm_getBatchByNumber", types.ToBatchNumArg(number), true) + if err != nil { + return nil, err + } + + if response.Error != nil { + return nil, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result *types.Batch + err = json.Unmarshal(response.Result, &result) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/jsonrpc/codec.go b/jsonrpc/codec.go deleted file mode 100644 index 69ca32e199..0000000000 --- a/jsonrpc/codec.go +++ /dev/null @@ -1,165 +0,0 @@ -package jsonrpc - -import ( - "context" - "encoding/json" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/jackc/pgx/v4" -) - -const ( - // PendingBlockNumber represents the pending block number - PendingBlockNumber = BlockNumber(-3) - // LatestBlockNumber represents the latest block number - LatestBlockNumber = BlockNumber(-2) - // EarliestBlockNumber represents the earliest block number - EarliestBlockNumber = BlockNumber(-1) - - // Earliest contains the string to represent the earliest block known. - Earliest = "earliest" - // Latest contains the string to represent the latest block known. - Latest = "latest" - // Pending contains the string to represent pending blocks. - Pending = "pending" -) - -// Request is a jsonrpc request -type Request struct { - JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id"` - Method string `json:"method"` - Params json.RawMessage `json:"params,omitempty"` -} - -// Response is a jsonrpc success response -type Response struct { - JSONRPC string - ID interface{} - Result json.RawMessage - Error *ErrorObject -} - -// ErrorObject is a jsonrpc error -type ErrorObject struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` -} - -// NewResponse returns Success/Error response object -func NewResponse(req Request, reply *[]byte, err rpcError) Response { - var result json.RawMessage - if reply != nil { - result = *reply - } - - var errorObj *ErrorObject - if err != nil { - errorObj = &ErrorObject{err.ErrorCode(), err.Error(), nil} - } - - return Response{ - JSONRPC: req.JSONRPC, - ID: req.ID, - Result: result, - Error: errorObj, - } -} - -// MarshalJSON customizes the JSON representation of the response. -func (r Response) MarshalJSON() ([]byte, error) { - if r.Error != nil { - return json.Marshal(struct { - JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id"` - Error *ErrorObject `json:"error"` - }{ - JSONRPC: r.JSONRPC, - ID: r.ID, - Error: r.Error, - }) - } - - return json.Marshal(struct { - JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id"` - Result json.RawMessage `json:"result"` - }{ - JSONRPC: r.JSONRPC, - ID: r.ID, - Result: r.Result, - }) -} - -// BlockNumber is the number of a ethereum block -type BlockNumber int64 - -// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called -func (b *BlockNumber) UnmarshalJSON(buffer []byte) error { - num, err := stringToBlockNumber(string(buffer)) - if err != nil { - return err - } - *b = num - return nil -} - -func (b *BlockNumber) getNumericBlockNumber(ctx context.Context, s stateInterface, dbTx pgx.Tx) (uint64, rpcError) { - bValue := LatestBlockNumber - if b != nil { - bValue = *b - } - - switch bValue { - case LatestBlockNumber, PendingBlockNumber: - lastBlockNumber, err := s.GetLastL2BlockNumber(ctx, dbTx) - if err != nil { - return 0, newRPCError(defaultErrorCode, "failed to get the last block number from state") - } - - return lastBlockNumber, nil - - case EarliestBlockNumber: - return 0, nil - - default: - if bValue < 0 { - return 0, newRPCError(invalidParamsErrorCode, "invalid block number: %v", bValue) - } - return uint64(bValue), nil - } -} - -func stringToBlockNumber(str string) (BlockNumber, error) { - str = strings.Trim(str, "\"") - switch str { - case Earliest: - return EarliestBlockNumber, nil - case Pending: - return PendingBlockNumber, nil - case Latest, "": - return LatestBlockNumber, nil - } - - n, err := encoding.DecodeUint64orHex(&str) - if err != nil { - return 0, err - } - return BlockNumber(n), nil -} - -// Index of a item -type Index int64 - -// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called -func (i *Index) UnmarshalJSON(buffer []byte) error { - str := strings.Trim(string(buffer), "\"") - n, err := encoding.DecodeUint64orHex(&str) - if err != nil { - return err - } - *i = Index(n) - return nil -} diff --git a/jsonrpc/config.go b/jsonrpc/config.go index 8b9f63983b..5284c67152 100644 --- a/jsonrpc/config.go +++ b/jsonrpc/config.go @@ -1,32 +1,49 @@ package jsonrpc -import "github.com/0xPolygonHermez/zkevm-node/db" +import "github.com/0xPolygonHermez/zkevm-node/config/types" // Config represents the configuration of the json rpc type Config struct { + // Host defines the network adapter that will be used to serve the HTTP requests Host string `mapstructure:"Host"` - Port int `mapstructure:"Port"` + // Port defines the port to serve the endpoints via HTTP + Port int `mapstructure:"Port"` + + // ReadTimeout is the HTTP server read timeout + // check net/http.server.ReadTimeout and net/http.server.ReadHeaderTimeout + ReadTimeout types.Duration `mapstructure:"ReadTimeout"` + + // WriteTimeout is the HTTP server write timeout + // check net/http.server.WriteTimeout + WriteTimeout types.Duration `mapstructure:"WriteTimeout"` + + // MaxRequestsPerIPAndSecond defines how much requests a single IP can + // send within a single second MaxRequestsPerIPAndSecond float64 `mapstructure:"MaxRequestsPerIPAndSecond"` // SequencerNodeURI is used allow Non-Sequencer nodes // to relay transactions to the Sequencer node SequencerNodeURI string `mapstructure:"SequencerNodeURI"` - // BroadcastURI is the URL of the Trusted State broadcast service - BroadcastURI string `mapstructure:"BroadcastURI"` - - // DefaultSenderAddress is the address that jRPC will use - // to communicate with the state for eth_EstimateGas and eth_Call when - // the From field is not specified because it is optional - DefaultSenderAddress string `mapstructure:"DefaultSenderAddress"` - // MaxCumulativeGasUsed is the max gas allowed per batch MaxCumulativeGasUsed uint64 - // ChainID is the L2 ChainID provided by the Network Config - ChainID uint64 + // WebSockets configuration + WebSockets WebSocketsConfig `mapstructure:"WebSockets"` + + // EnableL2SuggestedGasPricePolling enables polling of the L2 gas price to block tx in the RPC with lower gas price. + EnableL2SuggestedGasPricePolling bool `mapstructure:"EnableL2SuggestedGasPricePolling"` +} + +// WebSocketsConfig has parameters to config the rpc websocket support +type WebSocketsConfig struct { + // Enabled defines if the WebSocket requests are enabled or disabled + Enabled bool `mapstructure:"Enabled"` + + // Host defines the network adapter that will be used to serve the WS requests + Host string `mapstructure:"Host"` - // RPC Database COnfig - DB db.Config `mapstructure:"DB"` + // Port defines the port to serve the endpoints via WS + Port int `mapstructure:"Port"` } diff --git a/jsonrpc/dbtxmanager.go b/jsonrpc/dbtxmanager.go index 59c363303e..ef43f91791 100644 --- a/jsonrpc/dbtxmanager.go +++ b/jsonrpc/dbtxmanager.go @@ -3,30 +3,31 @@ package jsonrpc import ( "context" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/jackc/pgx/v4" ) type dbTxManager struct{} -type dbTxScopedFn func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) +type dbTxScopedFn func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) -func (f *dbTxManager) NewDbTxScope(st stateInterface, scopedFn dbTxScopedFn) (interface{}, rpcError) { +func (f *dbTxManager) NewDbTxScope(st types.StateInterface, scopedFn dbTxScopedFn) (interface{}, types.Error) { ctx := context.Background() dbTx, err := st.BeginStateTransaction(ctx) if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to connect to the state", err) + return rpcErrorResponse(types.DefaultErrorCode, "failed to connect to the state", err) } v, rpcErr := scopedFn(ctx, dbTx) if rpcErr != nil { if txErr := dbTx.Rollback(context.Background()); txErr != nil { - return rpcErrorResponse(defaultErrorCode, "failed to rollback db transaction", txErr) + return rpcErrorResponse(types.DefaultErrorCode, "failed to rollback db transaction", txErr) } return v, rpcErr } if txErr := dbTx.Commit(context.Background()); txErr != nil { - return rpcErrorResponse(defaultErrorCode, "failed to commit db transaction", txErr) + return rpcErrorResponse(types.DefaultErrorCode, "failed to commit db transaction", txErr) } return v, rpcErr } diff --git a/jsonrpc/dbtxmanager_test.go b/jsonrpc/dbtxmanager_test.go index 5ae20d58da..0f4bb6c893 100644 --- a/jsonrpc/dbtxmanager_test.go +++ b/jsonrpc/dbtxmanager_test.go @@ -5,6 +5,8 @@ import ( "errors" "testing" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/mocks" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/jackc/pgx/v4" "github.com/stretchr/testify/assert" ) @@ -14,66 +16,66 @@ func TestNewDbTxScope(t *testing.T) { Name string Fn dbTxScopedFn ExpectedResult interface{} - ExpectedError rpcError - SetupMocks func(s *stateMock, d *dbTxMock) + ExpectedError types.Error + SetupMocks func(s *mocks.StateMock, d *mocks.DBTxMock) } testCases := []testCase{ { Name: "Run scoped func commits DB tx", - Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { + Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { return 1, nil }, ExpectedResult: 1, ExpectedError: nil, - SetupMocks: func(s *stateMock, d *dbTxMock) { + SetupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock) { d.On("Commit", context.Background()).Return(nil).Once() s.On("BeginStateTransaction", context.Background()).Return(d, nil).Once() }, }, { Name: "Run scoped func rollbacks DB tx", - Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - return nil, newRPCError(defaultErrorCode, "func returned an error") + Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + return nil, types.NewRPCError(types.DefaultErrorCode, "func returned an error") }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "func returned an error"), - SetupMocks: func(s *stateMock, d *dbTxMock) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "func returned an error"), + SetupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock) { d.On("Rollback", context.Background()).Return(nil).Once() s.On("BeginStateTransaction", context.Background()).Return(d, nil).Once() }, }, { Name: "Run scoped func but fails create a db tx", - Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { + Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { return nil, nil }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to connect to the state"), - SetupMocks: func(s *stateMock, d *dbTxMock) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to connect to the state"), + SetupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock) { s.On("BeginStateTransaction", context.Background()).Return(nil, errors.New("failed to create db tx")).Once() }, }, { Name: "Run scoped func but fails to commit DB tx", - Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { + Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { return 1, nil }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to commit db transaction"), - SetupMocks: func(s *stateMock, d *dbTxMock) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to commit db transaction"), + SetupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock) { d.On("Commit", context.Background()).Return(errors.New("failed to commit db tx")).Once() s.On("BeginStateTransaction", context.Background()).Return(d, nil).Once() }, }, { Name: "Run scoped func but fails to rollbacks DB tx", - Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - return nil, newRPCError(defaultErrorCode, "func returned an error") + Fn: func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + return nil, types.NewRPCError(types.DefaultErrorCode, "func returned an error") }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to rollback db transaction"), - SetupMocks: func(s *stateMock, d *dbTxMock) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to rollback db transaction"), + SetupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock) { d.On("Rollback", context.Background()).Return(errors.New("failed to rollback db tx")).Once() s.On("BeginStateTransaction", context.Background()).Return(d, nil).Once() }, @@ -81,8 +83,8 @@ func TestNewDbTxScope(t *testing.T) { } dbTxManager := dbTxManager{} - s := newStateMock(t) - d := newDbTxMock(t) + s := mocks.NewStateMock(t) + d := mocks.NewDBTxMock(t) for _, testCase := range testCases { t.Run(testCase.Name, func(t *testing.T) { diff --git a/jsonrpc/debug.go b/jsonrpc/debug.go deleted file mode 100644 index 1dffecb62e..0000000000 --- a/jsonrpc/debug.go +++ /dev/null @@ -1,122 +0,0 @@ -package jsonrpc - -import ( - "context" - - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/ethereum/go-ethereum/common" - "github.com/jackc/pgx/v4" -) - -// Debug is the debug jsonrpc endpoint -type Debug struct { - state stateInterface - txMan dbTxManager -} - -type traceConfig struct { - Tracer *string `json:"tracer"` -} - -type traceTransactionResponse struct { - Gas uint64 `json:"gas"` - Failed bool `json:"failed"` - ReturnValue interface{} `json:"returnValue"` - StructLogs []StructLogRes `json:"structLogs"` -} - -// StructLogRes represents a log response. -type StructLogRes struct { - Pc uint64 `json:"pc"` - Op string `json:"op"` - Gas uint64 `json:"gas"` - GasCost uint64 `json:"gasCost"` - Depth int `json:"depth"` - Error string `json:"error,omitempty"` - Stack *[]argBig `json:"stack,omitempty"` - Memory *argBytes `json:"memory,omitempty"` - Storage *map[string]string `json:"storage,omitempty"` - RefundCounter uint64 `json:"refund,omitempty"` -} - -// TraceTransaction creates a response for debug_traceTransaction request. -// See https://geth.ethereum.org/docs/rpc/ns-debug#debug_tracetransaction -func (d *Debug) TraceTransaction(hash common.Hash, cfg *traceConfig) (interface{}, rpcError) { - return d.txMan.NewDbTxScope(d.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - tracer := "" - if cfg != nil && cfg.Tracer != nil { - tracer = *cfg.Tracer - } - - result, err := d.state.DebugTransaction(ctx, hash, tracer, dbTx) - if err != nil { - const errorMessage = "failed to debug trace the transaction" - log.Debugf("%v: %v", errorMessage, err) - return nil, newRPCError(defaultErrorCode, errorMessage) - } - - if tracer != "" && len(result.ExecutorTraceResult) > 0 { - return result.ExecutorTraceResult, nil - } - - failed := result.Failed() - structLogs := make([]StructLogRes, 0, len(result.StructLogs)) - for _, structLog := range result.StructLogs { - var stackRes *[]argBig - if len(structLog.Stack) > 0 { - stack := make([]argBig, 0, len(structLog.Stack)) - for _, stackItem := range structLog.Stack { - if stackItem != nil { - stack = append(stack, argBig(*stackItem)) - } - } - stackRes = &stack - } - - var memoryRes *argBytes - if len(structLog.Memory) > 0 { - memory := make(argBytes, 0, len(structLog.Memory)) - for _, memoryItem := range structLog.Memory { - memory = append(memory, memoryItem) - } - memoryRes = &memory - } - - var storageRes *map[string]string - if len(structLog.Storage) > 0 { - storage := make(map[string]string, len(structLog.Storage)) - for storageKey, storageValue := range structLog.Storage { - storage[storageKey.Hex()] = storageValue.Hex() - } - storageRes = &storage - } - - errRes := "" - if structLog.Err != nil { - errRes = structLog.Err.Error() - } - - structLogs = append(structLogs, StructLogRes{ - Pc: structLog.Pc, - Op: structLog.Op, - Gas: structLog.Gas, - GasCost: structLog.GasCost, - Depth: structLog.Depth, - Error: errRes, - Stack: stackRes, - Memory: memoryRes, - Storage: storageRes, - RefundCounter: structLog.RefundCounter, - }) - } - - resp := traceTransactionResponse{ - Gas: result.GasUsed, - Failed: failed, - ReturnValue: result.ReturnValue, - StructLogs: structLogs, - } - - return resp, nil - }) -} diff --git a/jsonrpc/endpoints_debug.go b/jsonrpc/endpoints_debug.go new file mode 100644 index 0000000000..502bece0d9 --- /dev/null +++ b/jsonrpc/endpoints_debug.go @@ -0,0 +1,273 @@ +package jsonrpc + +import ( + "context" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +var defaultTraceConfig = &traceConfig{ + DisableStorage: false, + DisableStack: false, + EnableMemory: false, + EnableReturnData: false, + Tracer: nil, +} + +// DebugEndpoints is the debug jsonrpc endpoint +type DebugEndpoints struct { + state types.StateInterface + txMan dbTxManager +} + +type traceConfig struct { + DisableStorage bool `json:"disableStorage"` + DisableStack bool `json:"disableStack"` + EnableMemory bool `json:"enableMemory"` + EnableReturnData bool `json:"enableReturnData"` + Tracer *string `json:"tracer"` + TracerConfig json.RawMessage `json:"tracerConfig"` +} + +// StructLogRes represents the debug trace information for each opcode +type StructLogRes struct { + Pc uint64 `json:"pc"` + Op string `json:"op"` + Gas uint64 `json:"gas"` + GasCost uint64 `json:"gasCost"` + Depth int `json:"depth"` + Error string `json:"error,omitempty"` + Stack *[]types.ArgBig `json:"stack,omitempty"` + Memory *[]string `json:"memory,omitempty"` + Storage *map[string]string `json:"storage,omitempty"` + RefundCounter uint64 `json:"refund,omitempty"` +} + +type traceTransactionResponse struct { + Gas uint64 `json:"gas"` + Failed bool `json:"failed"` + ReturnValue interface{} `json:"returnValue"` + StructLogs []StructLogRes `json:"structLogs"` +} + +type traceBlockTransactionResponse struct { + Result interface{} `json:"result"` +} + +// TraceTransaction creates a response for debug_traceTransaction request. +// See https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtracetransaction +func (d *DebugEndpoints) TraceTransaction(hash types.ArgHash, cfg *traceConfig) (interface{}, types.Error) { + return d.txMan.NewDbTxScope(d.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + return d.buildTraceTransaction(ctx, hash.Hash(), cfg, dbTx) + }) +} + +// TraceBlockByNumber creates a response for debug_traceBlockByNumber request. +// See https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtraceblockbynumber +func (d *DebugEndpoints) TraceBlockByNumber(number types.BlockNumber, cfg *traceConfig) (interface{}, types.Error) { + return d.txMan.NewDbTxScope(d.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + blockNumber, rpcErr := number.GetNumericBlockNumber(ctx, d.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + block, err := d.state.GetL2BlockByNumber(ctx, blockNumber, dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("block #%d not found", blockNumber)) + } else if err == state.ErrNotFound { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get block by number", err) + } + + traces, rpcErr := d.buildTraceBlock(ctx, block.Transactions(), cfg, dbTx) + if err != nil { + return nil, rpcErr + } + + return traces, nil + }) +} + +// TraceBlockByHash creates a response for debug_traceBlockByHash request. +// See https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-debug#debugtraceblockbyhash +func (d *DebugEndpoints) TraceBlockByHash(hash types.ArgHash, cfg *traceConfig) (interface{}, types.Error) { + return d.txMan.NewDbTxScope(d.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + block, err := d.state.GetL2BlockByHash(ctx, hash.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("block %s not found", hash.Hash().String())) + } else if err == state.ErrNotFound { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get block by hash", err) + } + + traces, rpcErr := d.buildTraceBlock(ctx, block.Transactions(), cfg, dbTx) + if err != nil { + return nil, rpcErr + } + + return traces, nil + }) +} + +func (d *DebugEndpoints) buildTraceBlock(ctx context.Context, txs []*ethTypes.Transaction, cfg *traceConfig, dbTx pgx.Tx) (interface{}, types.Error) { + traces := []traceBlockTransactionResponse{} + for _, tx := range txs { + traceTransaction, err := d.buildTraceTransaction(ctx, tx.Hash(), cfg, dbTx) + if err != nil { + errMsg := fmt.Sprintf("failed to get trace for transaction %v", tx.Hash().String()) + return rpcErrorResponse(types.DefaultErrorCode, errMsg, err) + } + traceBlockTransaction := traceBlockTransactionResponse{ + Result: traceTransaction, + } + traces = append(traces, traceBlockTransaction) + } + + return traces, nil +} + +func (d *DebugEndpoints) buildTraceTransaction(ctx context.Context, hash common.Hash, cfg *traceConfig, dbTx pgx.Tx) (interface{}, types.Error) { + traceCfg := cfg + if traceCfg == nil { + traceCfg = defaultTraceConfig + } + + // check tracer + if traceCfg.Tracer != nil && *traceCfg.Tracer != "" && !isBuiltInTracer(*traceCfg.Tracer) && !isJSCustomTracer(*traceCfg.Tracer) { + return rpcErrorResponse(types.DefaultErrorCode, "invalid tracer", nil) + } + + stateTraceConfig := state.TraceConfig{ + DisableStack: traceCfg.DisableStack, + DisableStorage: traceCfg.DisableStorage, + EnableMemory: traceCfg.EnableMemory, + EnableReturnData: traceCfg.EnableReturnData, + Tracer: traceCfg.Tracer, + TracerConfig: traceCfg.TracerConfig, + } + result, err := d.state.DebugTransaction(ctx, hash, stateTraceConfig, dbTx) + if errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, "transaction not found", nil) + } else if err != nil { + const errorMessage = "failed to get trace" + log.Errorf("%v: %v", errorMessage, err) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + // if a tracer was specified, then return the trace result + if stateTraceConfig.Tracer != nil && *stateTraceConfig.Tracer != "" && len(result.ExecutorTraceResult) > 0 { + return result.ExecutorTraceResult, nil + } + + receipt, err := d.state.GetTransactionReceipt(ctx, hash, dbTx) + if err != nil { + const errorMessage = "failed to tx receipt" + log.Errorf("%v: %v", errorMessage, err) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + failed := receipt.Status == ethTypes.ReceiptStatusFailed + var returnValue interface{} + if stateTraceConfig.EnableReturnData { + returnValue = common.Bytes2Hex(result.ReturnValue) + } + + structLogs := d.buildStructLogs(result.StructLogs, *traceCfg) + + resp := traceTransactionResponse{ + Gas: result.GasUsed, + Failed: failed, + ReturnValue: returnValue, + StructLogs: structLogs, + } + + return resp, nil +} + +func (d *DebugEndpoints) buildStructLogs(stateStructLogs []instrumentation.StructLog, cfg traceConfig) []StructLogRes { + structLogs := make([]StructLogRes, 0, len(stateStructLogs)) + for _, structLog := range stateStructLogs { + errRes := "" + if structLog.Err != nil { + errRes = structLog.Err.Error() + } + + op := structLog.Op + if op == "SHA3" { + op = "KECCAK256" + } + + structLogRes := StructLogRes{ + Pc: structLog.Pc, + Op: op, + Gas: structLog.Gas, + GasCost: structLog.GasCost, + Depth: structLog.Depth, + Error: errRes, + RefundCounter: structLog.RefundCounter, + } + + if !cfg.DisableStack { + stack := make([]types.ArgBig, 0, len(structLog.Stack)) + for _, stackItem := range structLog.Stack { + if stackItem != nil { + stack = append(stack, types.ArgBig(*stackItem)) + } + } + structLogRes.Stack = &stack + } + + if cfg.EnableMemory { + const memoryChunkSize = 32 + memory := make([]string, 0, len(structLog.Memory)) + for i := 0; i < len(structLog.Memory); i = i + memoryChunkSize { + slice32Bytes := make([]byte, memoryChunkSize) + copy(slice32Bytes, structLog.Memory[i:i+memoryChunkSize]) + memoryStringItem := hex.EncodeToString(slice32Bytes) + memory = append(memory, memoryStringItem) + } + structLogRes.Memory = &memory + } + + if !cfg.DisableStorage && len(structLog.Storage) > 0 { + storage := make(map[string]string, len(structLog.Storage)) + for storageKey, storageValue := range structLog.Storage { + k := hex.EncodeToString(storageKey.Bytes()) + v := hex.EncodeToString(storageValue.Bytes()) + storage[k] = v + } + structLogRes.Storage = &storage + } + + structLogs = append(structLogs, structLogRes) + } + return structLogs +} + +// isBuiltInTracer checks if the tracer is one of the +// built-in tracers +func isBuiltInTracer(tracer string) bool { + // built-in tracers + switch tracer { + case "callTracer", "4byteTracer", "prestateTracer", "noopTracer": + return true + default: + return false + } +} + +// isJSCustomTracer checks if the tracer contains the +// functions result and fault which are required for a custom tracer +// https://geth.ethereum.org/docs/developers/evm-tracing/custom-tracer +func isJSCustomTracer(tracer string) bool { + return strings.Contains(tracer, "result") && strings.Contains(tracer, "fault") +} diff --git a/jsonrpc/endpoints_eth.go b/jsonrpc/endpoints_eth.go new file mode 100644 index 0000000000..7b3aa335f3 --- /dev/null +++ b/jsonrpc/endpoints_eth.go @@ -0,0 +1,1024 @@ +package jsonrpc + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "net/http" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/gorilla/websocket" + "github.com/jackc/pgx/v4" +) + +const ( + // DefaultSenderAddress is the address that jRPC will use + // to communicate with the state for eth_EstimateGas and eth_Call when + // the From field is not specified because it is optional + DefaultSenderAddress = "0x1111111111111111111111111111111111111111" +) + +// EthEndpoints contains implementations for the "eth" RPC endpoints +type EthEndpoints struct { + cfg Config + chainID uint64 + pool types.PoolInterface + state types.StateInterface + storage storageInterface + txMan dbTxManager +} + +// newEthEndpoints creates an new instance of Eth +func newEthEndpoints(cfg Config, chainID uint64, p types.PoolInterface, s types.StateInterface, storage storageInterface) *EthEndpoints { + e := &EthEndpoints{cfg: cfg, chainID: chainID, pool: p, state: s, storage: storage} + s.RegisterNewL2BlockEventHandler(e.onNewL2Block) + + return e +} + +// BlockNumber returns current block number +func (e *EthEndpoints) BlockNumber() (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + lastBlockNumber, err := e.state.GetLastL2BlockNumber(ctx, dbTx) + if err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state") + } + + return hex.EncodeUint64(lastBlockNumber), nil + }) +} + +// Call executes a new message call immediately and returns the value of +// executed contract and potential error. +// Note, this function doesn't make any changes in the state/blockchain and is +// useful to execute view/pure methods and retrieve values. +func (e *EthEndpoints) Call(arg *types.TxArgs, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + if arg == nil { + return rpcErrorResponse(types.InvalidParamsErrorCode, "missing value for required argument 0", nil) + } else if blockArg == nil { + return rpcErrorResponse(types.InvalidParamsErrorCode, "missing value for required argument 1", nil) + } + block, respErr := e.getBlockByArg(ctx, blockArg, dbTx) + if respErr != nil { + return nil, respErr + } + var blockToProcess *uint64 + if blockArg != nil { + blockNumArg := blockArg.Number() + if blockNumArg != nil && (*blockArg.Number() == types.LatestBlockNumber || *blockArg.Number() == types.PendingBlockNumber) { + blockToProcess = nil + } else { + n := block.NumberU64() + blockToProcess = &n + } + } + + // If the caller didn't supply the gas limit in the message, then we set it to maximum possible => block gas limit + if arg.Gas == nil || uint64(*arg.Gas) <= 0 { + header, err := e.state.GetL2BlockHeaderByNumber(ctx, block.NumberU64(), dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get block header", err) + } + + gas := types.ArgUint64(header.GasLimit) + arg.Gas = &gas + } + + defaultSenderAddress := common.HexToAddress(DefaultSenderAddress) + sender, tx, err := arg.ToTransaction(ctx, e.state, e.cfg.MaxCumulativeGasUsed, block.Root(), defaultSenderAddress, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to convert arguments into an unsigned transaction", err) + } + + result, err := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockToProcess, true, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to execute the unsigned transaction", err) + } + + if result.Reverted() { + data := make([]byte, len(result.ReturnValue)) + copy(data, result.ReturnValue) + return nil, types.NewRPCErrorWithData(types.RevertedErrorCode, result.Err.Error(), &data) + } else if result.Failed() { + return nil, types.NewRPCErrorWithData(types.DefaultErrorCode, result.Err.Error(), nil) + } + + return types.ArgBytesPtr(result.ReturnValue), nil + }) +} + +// ChainId returns the chain id of the client +func (e *EthEndpoints) ChainId() (interface{}, types.Error) { //nolint:revive + return hex.EncodeUint64(e.chainID), nil +} + +// EstimateGas generates and returns an estimate of how much gas is necessary to +// allow the transaction to complete. +// The transaction will not be added to the blockchain. +// Note that the estimate may be significantly more than the amount of gas actually +// used by the transaction, for a variety of reasons including EVM mechanics and +// node performance. +func (e *EthEndpoints) EstimateGas(arg *types.TxArgs, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + if arg == nil { + return rpcErrorResponse(types.InvalidParamsErrorCode, "missing value for required argument 0", nil) + } + + block, respErr := e.getBlockByArg(ctx, blockArg, dbTx) + if respErr != nil { + return nil, respErr + } + + var blockToProcess *uint64 + if blockArg != nil { + blockNumArg := blockArg.Number() + if blockNumArg != nil && (*blockArg.Number() == types.LatestBlockNumber || *blockArg.Number() == types.PendingBlockNumber) { + blockToProcess = nil + } else { + n := block.NumberU64() + blockToProcess = &n + } + } + + defaultSenderAddress := common.HexToAddress(DefaultSenderAddress) + sender, tx, err := arg.ToTransaction(ctx, e.state, e.cfg.MaxCumulativeGasUsed, block.Root(), defaultSenderAddress, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to convert arguments into an unsigned transaction", err) + } + + gasEstimation, returnValue, err := e.state.EstimateGas(tx, sender, blockToProcess, dbTx) + if errors.Is(err, runtime.ErrExecutionReverted) { + data := make([]byte, len(returnValue)) + copy(data, returnValue) + return nil, types.NewRPCErrorWithData(types.RevertedErrorCode, err.Error(), &data) + } else if err != nil { + return nil, types.NewRPCErrorWithData(types.DefaultErrorCode, err.Error(), nil) + } + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, err.Error(), nil) + } + return hex.EncodeUint64(gasEstimation), nil + }) +} + +// GasPrice returns the average gas price based on the last x blocks +func (e *EthEndpoints) GasPrice() (interface{}, types.Error) { + ctx := context.Background() + if e.cfg.SequencerNodeURI != "" { + return e.getPriceFromSequencerNode() + } + gasPrice, err := e.pool.GetGasPrice(ctx) + if err != nil { + return "0x0", nil + } + return hex.EncodeUint64(gasPrice), nil +} + +func (e *EthEndpoints) getPriceFromSequencerNode() (interface{}, types.Error) { + res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_gasPrice") + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get gas price from sequencer node", err) + } + + if res.Error != nil { + return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) + } + + var gasPrice types.ArgUint64 + err = json.Unmarshal(res.Result, &gasPrice) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to read gas price from sequencer node", err) + } + return gasPrice, nil +} + +// GetBalance returns the account's balance at the referenced block +func (e *EthEndpoints) GetBalance(address types.ArgAddress, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + block, rpcErr := e.getBlockByArg(ctx, blockArg, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + balance, err := e.state.GetBalance(ctx, address.Address(), block.Root()) + if errors.Is(err, state.ErrNotFound) { + return hex.EncodeUint64(0), nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get balance from state", err) + } + + return hex.EncodeBig(balance), nil + }) +} + +func (e *EthEndpoints) getBlockByArg(ctx context.Context, blockArg *types.BlockNumberOrHash, dbTx pgx.Tx) (*ethTypes.Block, types.Error) { + // If no block argument is provided, return the latest block + if blockArg == nil { + block, err := e.state.GetLastL2Block(ctx, dbTx) + if err != nil { + return nil, types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state") + } + return block, nil + } + + // If we have a block hash, try to get the block by hash + if blockArg.IsHash() { + block, err := e.state.GetL2BlockByHash(ctx, blockArg.Hash().Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, types.NewRPCError(types.DefaultErrorCode, "header for hash not found") + } else if err != nil { + return nil, types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get block by hash %v", blockArg.Hash().Hash())) + } + return block, nil + } + + // Otherwise, try to get the block by number + blockNum, rpcErr := blockArg.Number().GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + block, err := e.state.GetL2BlockByNumber(context.Background(), blockNum, dbTx) + if errors.Is(err, state.ErrNotFound) || block == nil { + return nil, types.NewRPCError(types.DefaultErrorCode, "header not found") + } else if err != nil { + return nil, types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get block by number %v", blockNum)) + } + + return block, nil +} + +// GetBlockByHash returns information about a block by hash +func (e *EthEndpoints) GetBlockByHash(hash types.ArgHash, fullTx bool) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + block, err := e.state.GetL2BlockByHash(ctx, hash.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get block by hash from state", err) + } + + rpcBlock := types.NewBlock(block, fullTx) + + return rpcBlock, nil + }) +} + +// GetBlockByNumber returns information about a block by block number +func (e *EthEndpoints) GetBlockByNumber(number types.BlockNumber, fullTx bool) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + if number == types.PendingBlockNumber { + lastBlock, err := e.state.GetLastL2Block(ctx, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "couldn't load last block from state to compute the pending block", err) + } + header := ethTypes.CopyHeader(lastBlock.Header()) + header.ParentHash = lastBlock.Hash() + header.Number = big.NewInt(0).SetUint64(lastBlock.Number().Uint64() + 1) + header.TxHash = ethTypes.EmptyRootHash + header.UncleHash = ethTypes.EmptyUncleHash + block := ethTypes.NewBlockWithHeader(header) + rpcBlock := types.NewBlock(block, fullTx) + + return rpcBlock, nil + } + var err error + blockNumber, rpcErr := number.GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + block, err := e.state.GetL2BlockByNumber(ctx, blockNumber, dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load block from state by number %v", blockNumber), err) + } + + rpcBlock := types.NewBlock(block, fullTx) + + return rpcBlock, nil + }) +} + +// GetCode returns account code at given block number +func (e *EthEndpoints) GetCode(address types.ArgAddress, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + var err error + block, rpcErr := e.getBlockByArg(ctx, blockArg, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + code, err := e.state.GetCode(ctx, address.Address(), block.Root()) + if errors.Is(err, state.ErrNotFound) { + return "0x", nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get code", err) + } + + return types.ArgBytes(code), nil + }) +} + +// GetCompilers eth_getCompilers +func (e *EthEndpoints) GetCompilers() (interface{}, types.Error) { + return []interface{}{}, nil +} + +// GetFilterChanges polling method for a filter, which returns +// an array of logs which occurred since last poll. +func (e *EthEndpoints) GetFilterChanges(filterID string) (interface{}, types.Error) { + filter, err := e.storage.GetFilter(filterID) + if errors.Is(err, ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, "filter not found", err) + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get filter from storage", err) + } + + switch filter.Type { + case FilterTypeBlock: + { + res, err := e.state.GetL2BlockHashesSince(context.Background(), filter.LastPoll, nil) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get block hashes", err) + } + rpcErr := e.updateFilterLastPoll(filter.ID) + if rpcErr != nil { + return nil, rpcErr + } + if len(res) == 0 { + return nil, nil + } + return res, nil + } + case FilterTypePendingTx: + { + res, err := e.pool.GetPendingTxHashesSince(context.Background(), filter.LastPoll) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get pending transaction hashes", err) + } + rpcErr := e.updateFilterLastPoll(filter.ID) + if rpcErr != nil { + return nil, rpcErr + } + if len(res) == 0 { + return nil, nil + } + return res, nil + } + case FilterTypeLog: + { + filterParameters := filter.Parameters.(LogFilter) + filterParameters.Since = &filter.LastPoll + + resInterface, err := e.internalGetLogs(context.Background(), nil, filterParameters) + if err != nil { + return nil, err + } + rpcErr := e.updateFilterLastPoll(filter.ID) + if rpcErr != nil { + return nil, rpcErr + } + res := resInterface.([]types.Log) + if len(res) == 0 { + return nil, nil + } + return res, nil + } + default: + return nil, nil + } +} + +// GetFilterLogs returns an array of all logs matching filter +// with given id. +func (e *EthEndpoints) GetFilterLogs(filterID string) (interface{}, types.Error) { + filter, err := e.storage.GetFilter(filterID) + if errors.Is(err, ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get filter from storage", err) + } + + if filter.Type != FilterTypeLog { + return nil, nil + } + + filterParameters := filter.Parameters.(LogFilter) + filterParameters.Since = nil + + return e.GetLogs(filterParameters) +} + +// GetLogs returns a list of logs accordingly to the provided filter +func (e *EthEndpoints) GetLogs(filter LogFilter) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + return e.internalGetLogs(ctx, dbTx, filter) + }) +} + +func (e *EthEndpoints) internalGetLogs(ctx context.Context, dbTx pgx.Tx, filter LogFilter) (interface{}, types.Error) { + var err error + var fromBlock uint64 = 0 + if filter.FromBlock != nil { + var rpcErr types.Error + fromBlock, rpcErr = filter.FromBlock.GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + } + + toBlock, rpcErr := filter.ToBlock.GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + logs, err := e.state.GetLogs(ctx, fromBlock, toBlock, filter.Addresses, filter.Topics, filter.BlockHash, filter.Since, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get logs from state", err) + } + + result := make([]types.Log, 0, len(logs)) + for _, l := range logs { + result = append(result, types.NewLog(*l)) + } + + return result, nil +} + +// GetStorageAt gets the value stored for an specific address and position +func (e *EthEndpoints) GetStorageAt(address types.ArgAddress, storageKeyStr string, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + storageKey := types.ArgHash{} + err := storageKey.UnmarshalText([]byte(storageKeyStr)) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "unable to decode storage key: hex string invalid", nil) + } + + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + block, respErr := e.getBlockByArg(ctx, blockArg, dbTx) + if respErr != nil { + return nil, respErr + } + + value, err := e.state.GetStorageAt(ctx, address.Address(), storageKey.Hash().Big(), block.Root()) + if errors.Is(err, state.ErrNotFound) { + return types.ArgBytesPtr(common.Hash{}.Bytes()), nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get storage value from state", err) + } + + return types.ArgBytesPtr(common.BigToHash(value).Bytes()), nil + }) +} + +// GetTransactionByBlockHashAndIndex returns information about a transaction by +// block hash and transaction index position. +func (e *EthEndpoints) GetTransactionByBlockHashAndIndex(hash types.ArgHash, index types.Index) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + tx, err := e.state.GetTransactionByL2BlockHashAndIndex(ctx, hash.Hash(), uint64(index), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get transaction", err) + } + + receipt, err := e.state.GetTransactionReceipt(ctx, tx.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get transaction receipt", err) + } + + txIndex := uint64(receipt.TransactionIndex) + return types.NewTransaction(*tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil + }) +} + +// GetTransactionByBlockNumberAndIndex returns information about a transaction by +// block number and transaction index position. +func (e *EthEndpoints) GetTransactionByBlockNumberAndIndex(number *types.BlockNumber, index types.Index) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + var err error + blockNumber, rpcErr := number.GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + tx, err := e.state.GetTransactionByL2BlockNumberAndIndex(ctx, blockNumber, uint64(index), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get transaction", err) + } + + receipt, err := e.state.GetTransactionReceipt(ctx, tx.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get transaction receipt", err) + } + + txIndex := uint64(receipt.TransactionIndex) + return types.NewTransaction(*tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil + }) +} + +// GetTransactionByHash returns a transaction by his hash +func (e *EthEndpoints) GetTransactionByHash(hash types.ArgHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + // try to get tx from state + tx, err := e.state.GetTransactionByHash(ctx, hash.Hash(), dbTx) + if err != nil && !errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, "failed to load transaction by hash from state", err) + } + if tx != nil { + receipt, err := e.state.GetTransactionReceipt(ctx, hash.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, "transaction receipt not found", err) + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to load transaction receipt from state", err) + } + + txIndex := uint64(receipt.TransactionIndex) + return types.NewTransaction(*tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil + } + + // if the tx does not exist in the state, look for it in the pool + if e.cfg.SequencerNodeURI != "" { + return e.getTransactionByHashFromSequencerNode(hash.Hash()) + } + poolTx, err := e.pool.GetTxByHash(ctx, hash.Hash()) + if errors.Is(err, pool.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to load transaction by hash from pool", err) + } + tx = &poolTx.Transaction + + return types.NewTransaction(*tx, nil, nil, nil), nil + }) +} + +func (e *EthEndpoints) getTransactionByHashFromSequencerNode(hash common.Hash) (interface{}, types.Error) { + res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_getTransactionByHash", hash.String()) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get tx from sequencer node", err) + } + + if res.Error != nil { + return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) + } + + var tx *types.Transaction + err = json.Unmarshal(res.Result, &tx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to read tx from sequencer node", err) + } + return tx, nil +} + +// GetTransactionCount returns account nonce +func (e *EthEndpoints) GetTransactionCount(address types.ArgAddress, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + var ( + pendingNonce uint64 + nonce uint64 + err error + ) + + block, respErr := e.getBlockByArg(ctx, blockArg, dbTx) + if respErr != nil { + return nil, respErr + } + + if blockArg != nil { + blockNumArg := blockArg.Number() + if blockNumArg != nil && *blockNumArg == types.PendingBlockNumber { + if e.cfg.SequencerNodeURI != "" { + return e.getTransactionCountFromSequencerNode(address.Address(), blockArg.Number()) + } + pendingNonce, err = e.pool.GetNonce(ctx, address.Address()) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to count pending transactions", err) + } + } + } + + nonce, err = e.state.GetNonce(ctx, address.Address(), block.Root()) + + if errors.Is(err, state.ErrNotFound) { + return hex.EncodeUint64(0), nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to count transactions", err) + } + + if pendingNonce > nonce { + nonce = pendingNonce + } + + return hex.EncodeUint64(nonce), nil + }) +} + +func (e *EthEndpoints) getTransactionCountFromSequencerNode(address common.Address, number *types.BlockNumber) (interface{}, types.Error) { + res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_getTransactionCount", address.String(), number.StringOrHex()) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get nonce from sequencer node", err) + } + + if res.Error != nil { + return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) + } + + var nonce types.ArgUint64 + err = json.Unmarshal(res.Result, &nonce) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to read nonce from sequencer node", err) + } + return nonce, nil +} + +// GetBlockTransactionCountByHash returns the number of transactions in a +// block from a block matching the given block hash. +func (e *EthEndpoints) GetBlockTransactionCountByHash(hash types.ArgHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + c, err := e.state.GetL2BlockTransactionCountByHash(ctx, hash.Hash(), dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to count transactions", err) + } + + return types.ArgUint64(c), nil + }) +} + +// GetBlockTransactionCountByNumber returns the number of transactions in a +// block from a block matching the given block number. +func (e *EthEndpoints) GetBlockTransactionCountByNumber(number *types.BlockNumber) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + if number != nil && *number == types.PendingBlockNumber { + if e.cfg.SequencerNodeURI != "" { + return e.getBlockTransactionCountByNumberFromSequencerNode(number) + } + c, err := e.pool.CountPendingTransactions(ctx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to count pending transactions", err) + } + return types.ArgUint64(c), nil + } + + var err error + blockNumber, rpcErr := number.GetNumericBlockNumber(ctx, e.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + c, err := e.state.GetL2BlockTransactionCountByNumber(ctx, blockNumber, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to count transactions", err) + } + + return types.ArgUint64(c), nil + }) +} + +func (e *EthEndpoints) getBlockTransactionCountByNumberFromSequencerNode(number *types.BlockNumber) (interface{}, types.Error) { + res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_getBlockTransactionCountByNumber", number.StringOrHex()) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get tx count by block number from sequencer node", err) + } + + if res.Error != nil { + return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) + } + + var count types.ArgUint64 + err = json.Unmarshal(res.Result, &count) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to read tx count by block number from sequencer node", err) + } + return count, nil +} + +// GetTransactionReceipt returns a transaction receipt by his hash +func (e *EthEndpoints) GetTransactionReceipt(hash types.ArgHash) (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + tx, err := e.state.GetTransactionByHash(ctx, hash.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get tx from state", err) + } + + r, err := e.state.GetTransactionReceipt(ctx, hash.Hash(), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get tx receipt from state", err) + } + + receipt, err := types.NewReceipt(*tx, r) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to build the receipt response", err) + } + + return receipt, nil + }) +} + +// NewBlockFilter creates a filter in the node, to notify when +// a new block arrives. To check if the state has changed, +// call eth_getFilterChanges. +func (e *EthEndpoints) NewBlockFilter() (interface{}, types.Error) { + return e.newBlockFilter(nil) +} + +// internal +func (e *EthEndpoints) newBlockFilter(wsConn *websocket.Conn) (interface{}, types.Error) { + id, err := e.storage.NewBlockFilter(wsConn) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to create new block filter", err) + } + + return id, nil +} + +// NewFilter creates a filter object, based on filter options, +// to notify when the state changes (logs). To check if the state +// has changed, call eth_getFilterChanges. +func (e *EthEndpoints) NewFilter(filter LogFilter) (interface{}, types.Error) { + return e.newFilter(nil, filter) +} + +// internal +func (e *EthEndpoints) newFilter(wsConn *websocket.Conn, filter LogFilter) (interface{}, types.Error) { + id, err := e.storage.NewLogFilter(wsConn, filter) + if errors.Is(err, ErrFilterInvalidPayload) { + return rpcErrorResponse(types.InvalidParamsErrorCode, err.Error(), nil) + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to create new log filter", err) + } + + return id, nil +} + +// NewPendingTransactionFilter creates a filter in the node, to +// notify when new pending transactions arrive. To check if the +// state has changed, call eth_getFilterChanges. +func (e *EthEndpoints) NewPendingTransactionFilter() (interface{}, types.Error) { + return e.newPendingTransactionFilter(nil) +} + +// internal +func (e *EthEndpoints) newPendingTransactionFilter(wsConn *websocket.Conn) (interface{}, types.Error) { + return nil, types.NewRPCError(types.DefaultErrorCode, "not supported yet") + // id, err := e.storage.NewPendingTransactionFilter(wsConn) + // if err != nil { + // return rpcErrorResponse(types.DefaultErrorCode, "failed to create new pending transaction filter", err) + // } + + // return id, nil +} + +// SendRawTransaction has two different ways to handle new transactions: +// - for Sequencer nodes it tries to add the tx to the pool +// - for Non-Sequencer nodes it relays the Tx to the Sequencer node +func (e *EthEndpoints) SendRawTransaction(httpRequest *http.Request, input string) (interface{}, types.Error) { + if e.cfg.SequencerNodeURI != "" { + return e.relayTxToSequencerNode(input) + } else { + ip := "" + ips := httpRequest.Header.Get("X-Forwarded-For") + + if ips != "" { + ip = strings.Split(ips, ",")[0] + } + + return e.tryToAddTxToPool(input, ip) + } +} + +func (e *EthEndpoints) relayTxToSequencerNode(input string) (interface{}, types.Error) { + res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_sendRawTransaction", input) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to relay tx to the sequencer node", err) + } + + if res.Error != nil { + return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) + } + + txHash := res.Result + + return txHash, nil +} + +func (e *EthEndpoints) tryToAddTxToPool(input, ip string) (interface{}, types.Error) { + tx, err := hexToTx(input) + if err != nil { + return rpcErrorResponse(types.InvalidParamsErrorCode, "invalid tx input", err) + } + + log.Infof("adding TX to the pool: %v", tx.Hash().Hex()) + if err := e.pool.AddTx(context.Background(), *tx, ip); err != nil { + return rpcErrorResponse(types.DefaultErrorCode, err.Error(), nil) + } + log.Infof("TX added to the pool: %v", tx.Hash().Hex()) + + return tx.Hash().Hex(), nil +} + +// UninstallFilter uninstalls a filter with given id. +func (e *EthEndpoints) UninstallFilter(filterID string) (interface{}, types.Error) { + err := e.storage.UninstallFilter(filterID) + if errors.Is(err, ErrNotFound) { + return false, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to uninstall filter", err) + } + + return true, nil +} + +// Syncing returns an object with data about the sync status or false. +// https://eth.wiki/json-rpc/API#eth_syncing +func (e *EthEndpoints) Syncing() (interface{}, types.Error) { + return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + _, err := e.state.GetLastL2BlockNumber(ctx, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get last block number from state", err) + } + + syncInfo, err := e.state.GetSyncingInfo(ctx, dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, "failed to get syncing info from state", err) + } + + if syncInfo.CurrentBlockNumber == syncInfo.LastBlockNumberSeen { + return false, nil + } + + return struct { + S types.ArgUint64 `json:"startingBlock"` + C types.ArgUint64 `json:"currentBlock"` + H types.ArgUint64 `json:"highestBlock"` + }{ + S: types.ArgUint64(syncInfo.InitialSyncingBlock), + C: types.ArgUint64(syncInfo.CurrentBlockNumber), + H: types.ArgUint64(syncInfo.LastBlockNumberSeen), + }, nil + }) +} + +// GetUncleByBlockHashAndIndex returns information about a uncle of a +// block by hash and uncle index position +func (e *EthEndpoints) GetUncleByBlockHashAndIndex(hash types.ArgHash, index types.Index) (interface{}, types.Error) { + return nil, nil +} + +// GetUncleByBlockNumberAndIndex returns information about a uncle of a +// block by number and uncle index position +func (e *EthEndpoints) GetUncleByBlockNumberAndIndex(number types.BlockNumber, index types.Index) (interface{}, types.Error) { + return nil, nil +} + +// GetUncleCountByBlockHash returns the number of uncles in a block +// matching the given block hash +func (e *EthEndpoints) GetUncleCountByBlockHash(hash types.ArgAddress) (interface{}, types.Error) { + return "0x0", nil +} + +// GetUncleCountByBlockNumber returns the number of uncles in a block +// matching the given block number +func (e *EthEndpoints) GetUncleCountByBlockNumber(number types.BlockNumber) (interface{}, types.Error) { + return "0x0", nil +} + +// ProtocolVersion returns the protocol version. +func (e *EthEndpoints) ProtocolVersion() (interface{}, types.Error) { + return "0x0", nil +} + +func hexToTx(str string) (*ethTypes.Transaction, error) { + tx := new(ethTypes.Transaction) + + b, err := hex.DecodeHex(str) + if err != nil { + return nil, err + } + + if err := tx.UnmarshalBinary(b); err != nil { + return nil, err + } + + return tx, nil +} + +func (e *EthEndpoints) updateFilterLastPoll(filterID string) types.Error { + err := e.storage.UpdateFilterLastPoll(filterID) + if err != nil && !errors.Is(err, ErrNotFound) { + return types.NewRPCError(types.DefaultErrorCode, "failed to update last time the filter changes were requested") + } + return nil +} + +// Subscribe Creates a new subscription over particular events. +// The node will return a subscription id. +// For each event that matches the subscription a notification with relevant +// data is sent together with the subscription id. +func (e *EthEndpoints) Subscribe(wsConn *websocket.Conn, name string, logFilter *LogFilter) (interface{}, types.Error) { + switch name { + case "newHeads": + return e.newBlockFilter(wsConn) + case "logs": + var lf LogFilter + if logFilter != nil { + lf = *logFilter + } + return e.newFilter(wsConn, lf) + case "pendingTransactions", "newPendingTransactions": + return e.newPendingTransactionFilter(wsConn) + case "syncing": + return nil, types.NewRPCError(types.DefaultErrorCode, "not supported yet") + default: + return nil, types.NewRPCError(types.DefaultErrorCode, "invalid filter name") + } +} + +// Unsubscribe uninstalls the filter based on the provided filterID +func (e *EthEndpoints) Unsubscribe(wsConn *websocket.Conn, filterID string) (interface{}, types.Error) { + return e.UninstallFilter(filterID) +} + +// uninstallFilterByWSConn uninstalls the filters connected to the +// provided web socket connection +func (e *EthEndpoints) uninstallFilterByWSConn(wsConn *websocket.Conn) error { + return e.storage.UninstallFilterByWSConn(wsConn) +} + +// onNewL2Block is triggered when the state triggers the event for a new l2 block +func (e *EthEndpoints) onNewL2Block(event state.NewL2BlockEvent) { + blockFilters, err := e.storage.GetAllBlockFiltersWithWSConn() + if err != nil { + log.Errorf("failed to get all block filters with web sockets connections: %v", err) + } else { + for _, filter := range blockFilters { + b := types.NewBlock(&event.Block, false) + e.sendSubscriptionResponse(filter, b) + } + } + + logFilters, err := e.storage.GetAllLogFiltersWithWSConn() + if err != nil { + log.Errorf("failed to get all log filters with web sockets connections: %v", err) + } else { + for _, filter := range logFilters { + changes, err := e.GetFilterChanges(filter.ID) + if err != nil { + log.Errorf("failed to get filters changes for filter %v with web sockets connections: %v", filter.ID, err) + continue + } + + if changes != nil { + e.sendSubscriptionResponse(filter, changes) + } + } + } +} + +func (e *EthEndpoints) sendSubscriptionResponse(filter *Filter, data interface{}) { + const errMessage = "Unable to write WS message to filter %v, %s" + result, err := json.Marshal(data) + if err != nil { + log.Errorf(fmt.Sprintf(errMessage, filter.ID, err.Error())) + } + + res := types.SubscriptionResponse{ + JSONRPC: "2.0", + Method: "eth_subscription", + Params: types.SubscriptionResponseParams{ + Subscription: filter.ID, + Result: result, + }, + } + message, err := json.Marshal(res) + if err != nil { + log.Errorf(fmt.Sprintf(errMessage, filter.ID, err.Error())) + } + + err = filter.WsConn.WriteMessage(websocket.TextMessage, message) + if err != nil { + log.Errorf(fmt.Sprintf(errMessage, filter.ID, err.Error())) + } +} diff --git a/jsonrpc/eth_test.go b/jsonrpc/endpoints_eth_test.go similarity index 58% rename from jsonrpc/eth_test.go rename to jsonrpc/endpoints_eth_test.go index 6edf0e6f7e..a671c9109d 100644 --- a/jsonrpc/eth_test.go +++ b/jsonrpc/endpoints_eth_test.go @@ -11,21 +11,37 @@ import ( "github.com/0xPolygonHermez/zkevm-node/encoding" "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/state/runtime" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" + "github.com/gorilla/websocket" + "github.com/jackc/pgx/v4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) +var ( + latest = "latest" + blockNumOne = big.NewInt(1) + blockNumOneUint64 = blockNumOne.Uint64() + blockNumTen = big.NewInt(10) + blockNumTenUint64 = blockNumTen.Uint64() + addressArg = common.HexToAddress("0x123") + keyArg = common.HexToHash("0x123") + blockHash = common.HexToHash("0x82ba516e76a4bfaba6d1d95c8ccde96e353ce3c683231d011021f43dee7b2d95") + blockRoot = common.HexToHash("0xce3c683231d011021f43dee7b2d9582ba516e76a4bfaba6d1d95c8ccde96e353") + nilUint64 *uint64 +) + func TestBlockNumber(t *testing.T) { s, m, c := newSequencerMockedServer(t) defer s.Stop() @@ -34,15 +50,15 @@ func TestBlockNumber(t *testing.T) { Name string ExpectedResult uint64 ExpectedError interface{} - SetupMocks func(m *mocks) + SetupMocks func(m *mocksWrapper) } testCases := []testCase{ { Name: "get block number successfully", ExpectedError: nil, - ExpectedResult: 10, - SetupMocks: func(m *mocks) { + ExpectedResult: blockNumTen.Uint64(), + SetupMocks: func(m *mocksWrapper) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -55,15 +71,15 @@ func TestBlockNumber(t *testing.T) { m.State. On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(10), nil). + Return(blockNumTen.Uint64(), nil). Once() }, }, { Name: "failed to get block number", - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), ExpectedResult: 0, - SetupMocks: func(m *mocks) { + SetupMocks: func(m *mocksWrapper) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -91,8 +107,8 @@ func TestBlockNumber(t *testing.T) { assert.Equal(t, testCase.ExpectedResult, result) if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -104,205 +120,440 @@ func TestBlockNumber(t *testing.T) { } func TestCall(t *testing.T) { - s, m, c := newSequencerMockedServer(t) + s, m, _ := newSequencerMockedServer(t) defer s.Stop() type testCase struct { name string - from common.Address - to *common.Address - gas uint64 - gasPrice *big.Int - value *big.Int - data []byte - blockNumber *big.Int + params []interface{} expectedResult []byte expectedError interface{} - setupMocks func(Config, *mocks, *testCase) + setupMocks func(Config, *mocksWrapper, *testCase) } testCases := []*testCase{ { - name: "Transaction with all information", - from: common.HexToAddress("0x1"), - to: addressPtr(common.HexToAddress("0x2")), - gas: uint64(24000), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), + name: "Transaction with all information from a block with EIP-1898", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + map[string]interface{}{ + types.BlockNumberKey: hex.EncodeBig(blockNumOne), + }, + }, + expectedResult: []byte("hello world"), + expectedError: nil, + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + nonce := uint64(7) + m.DbTx.On("Commit", context.Background()).Return(nil).Once() + m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + match := tx != nil && + tx.To().Hex() == txArgs.To.Hex() && + tx.Gas() == uint64(*txArgs.Gas) && + tx.GasPrice().Uint64() == gasPrice.Uint64() && + tx.Value().Uint64() == value.Uint64() && + hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) && + tx.Nonce() == nonce + return match + }) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, &blockNumOneUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() + }, + }, + { + name: "Transaction with all information from block by hash with EIP-1898", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + map[string]interface{}{ + types.BlockHashKey: blockHash.String(), + }, + }, expectedResult: []byte("hello world"), expectedError: nil, - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(1) + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { nonce := uint64(7) m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumber, nil).Once() - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State. + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) return tx != nil && - tx.Gas() == testCase.gas && - tx.To().Hex() == testCase.to.Hex() && - tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() && - tx.Value().Uint64() == testCase.value.Uint64() && - hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) && + tx.To().Hex() == txArgs.To.Hex() && + tx.Gas() == uint64(*txArgs.Gas) && + tx.GasPrice().Uint64() == gasPrice.Uint64() && + tx.Value().Uint64() == value.Uint64() && + hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) && tx.Nonce() == nonce }) - m.State.On("GetNonce", context.Background(), testCase.from, blockNumber, m.DbTx).Return(nonce, nil).Once() - var nilBlockNumber *uint64 - m.State.On("ProcessUnsignedTransaction", context.Background(), txMatchBy, testCase.from, nilBlockNumber, true, m.DbTx).Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, &blockNumOneUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() }, }, { - name: "Transaction without from and gas from latest block", - to: addressPtr(common.HexToAddress("0x2")), - gasPrice: big.NewInt(0), - value: big.NewInt(2), - data: []byte("data"), + name: "Transaction with all information from latest block", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + latest, + }, expectedResult: []byte("hello world"), expectedError: nil, - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(1) - block := types.NewBlockWithHeader(&types.Header{Root: common.Hash{}, GasLimit: s.Config.MaxCumulativeGasUsed}) + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + nonce := uint64(7) m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumber, nil).Once() - m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { - hasTx := tx != nil - gasMatch := tx.Gas() == block.Header().GasLimit - toMatch := tx.To().Hex() == testCase.to.Hex() - gasPriceMatch := tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() - valueMatch := tx.Value().Uint64() == testCase.value.Uint64() - dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) - return hasTx && gasMatch && toMatch && gasPriceMatch && valueMatch && dataMatch + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + match := tx != nil && + tx.To().Hex() == txArgs.To.Hex() && + tx.Gas() == uint64(*txArgs.Gas) && + tx.GasPrice().Uint64() == gasPrice.Uint64() && + tx.Value().Uint64() == value.Uint64() && + hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) && + tx.Nonce() == nonce + return match }) - var nilBlockNumber *uint64 - m.State.On("ProcessUnsignedTransaction", context.Background(), txMatchBy, common.HexToAddress(c.DefaultSenderAddress), nilBlockNumber, true, m.DbTx).Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}).Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, nilUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() }, }, { - name: "Transaction without from and gas from pending block", - to: addressPtr(common.HexToAddress("0x2")), - gasPrice: big.NewInt(0), - value: big.NewInt(2), - data: []byte("data"), - blockNumber: big.NewInt(-1), + name: "Transaction with all information from block by hash", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + blockHash.String(), + }, expectedResult: []byte("hello world"), expectedError: nil, - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(1) - block := types.NewBlockWithHeader(&types.Header{Number: big.NewInt(1), Root: common.Hash{}, GasLimit: s.Config.MaxCumulativeGasUsed}) + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + nonce := uint64(7) m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumber, nil).Once() - m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State. + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + return tx != nil && + tx.To().Hex() == txArgs.To.Hex() && + tx.Gas() == uint64(*txArgs.Gas) && + tx.GasPrice().Uint64() == gasPrice.Uint64() && + tx.Value().Uint64() == value.Uint64() && + hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) && + tx.Nonce() == nonce + }) + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, &blockNumTenUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() + }, + }, + { + name: "Transaction with all information from block by number", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + "0xa", + }, + expectedResult: []byte("hello world"), + expectedError: nil, + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + nonce := uint64(7) + m.DbTx.On("Commit", context.Background()).Return(nil).Once() + m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + return tx != nil && + tx.To().Hex() == txArgs.To.Hex() && + tx.Gas() == uint64(*txArgs.Gas) && + tx.GasPrice().Uint64() == gasPrice.Uint64() && + tx.Value().Uint64() == value.Uint64() && + hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) && + tx.Nonce() == nonce + }) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumTenUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, &blockNumTenUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() + }, + }, + { + name: "Transaction without from and gas from latest block", + params: []interface{}{ + types.TxArgs{ + To: state.HexToAddressPtr("0x2"), + GasPrice: types.ArgBytesPtr(big.NewInt(0).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + latest, + }, + expectedResult: []byte("hello world"), + expectedError: nil, + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + blockHeader := ðTypes.Header{GasLimit: s.Config.MaxCumulativeGasUsed} + m.DbTx.On("Commit", context.Background()).Return(nil).Once() + m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + m.State.On("GetL2BlockHeaderByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(blockHeader, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) hasTx := tx != nil - gasMatch := tx.Gas() == block.Header().GasLimit - toMatch := tx.To().Hex() == testCase.to.Hex() - gasPriceMatch := tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() - valueMatch := tx.Value().Uint64() == testCase.value.Uint64() - dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) + gasMatch := tx.Gas() == blockHeader.GasLimit + toMatch := tx.To().Hex() == txArgs.To.Hex() + gasPriceMatch := tx.GasPrice().Uint64() == gasPrice.Uint64() + valueMatch := tx.Value().Uint64() == value.Uint64() + dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) return hasTx && gasMatch && toMatch && gasPriceMatch && valueMatch && dataMatch }) - var nilBlockNumber *uint64 - m.State.On("ProcessUnsignedTransaction", context.Background(), txMatchBy, common.HexToAddress(c.DefaultSenderAddress), nilBlockNumber, true, m.DbTx).Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}).Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, common.HexToAddress(DefaultSenderAddress), nilUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() }, }, { - name: "Transaction without from and gas and failed to get latest block header", - to: addressPtr(common.HexToAddress("0x2")), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), - expectedResult: nil, - expectedError: newRPCError(defaultErrorCode, "failed to get block header"), - setupMocks: func(c Config, m *mocks, testCase *testCase) { - m.DbTx.On("Rollback", context.Background()).Return(nil).Once() + name: "Transaction without from and gas from pending block", + params: []interface{}{ + types.TxArgs{ + To: state.HexToAddressPtr("0x2"), + GasPrice: types.ArgBytesPtr(big.NewInt(0).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + "pending", + }, + expectedResult: []byte("hello world"), + expectedError: nil, + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + blockHeader := ðTypes.Header{GasLimit: s.Config.MaxCumulativeGasUsed} + m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(nil, errors.New("failed to get last block")).Once() + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + m.State.On("GetL2BlockHeaderByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(blockHeader, nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + hasTx := tx != nil + gasMatch := tx.Gas() == blockHeader.GasLimit + toMatch := tx.To().Hex() == txArgs.To.Hex() + gasPriceMatch := tx.GasPrice().Uint64() == gasPrice.Uint64() + valueMatch := tx.Value().Uint64() == value.Uint64() + dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) + return hasTx && gasMatch && toMatch && gasPriceMatch && valueMatch && dataMatch + }) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, common.HexToAddress(DefaultSenderAddress), nilUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{ReturnValue: testCase.expectedResult}, nil). + Once() }, }, { - name: "Transaction without from and gas and failed to get pending block header", - to: addressPtr(common.HexToAddress("0x2")), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), - blockNumber: big.NewInt(-1), + name: "Transaction without from and gas and failed to get block header", + params: []interface{}{ + types.TxArgs{ + To: state.HexToAddressPtr("0x2"), + GasPrice: types.ArgBytesPtr(big.NewInt(0).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + latest, + }, expectedResult: nil, - expectedError: newRPCError(defaultErrorCode, "failed to get block header"), - setupMocks: func(c Config, m *mocks, testCase *testCase) { + expectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get block header"), + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { m.DbTx.On("Rollback", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(nil, errors.New("failed to get last block")).Once() + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetL2BlockHeaderByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(nil, errors.New("failed to get block header")).Once() }, }, { - name: "Transaction with gas but failed to get last block number", - from: common.HexToAddress("0x1"), - to: addressPtr(common.HexToAddress("0x2")), - gas: uint64(24000), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), + name: "Transaction with all information but failed to process unsigned transaction", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + latest, + }, expectedResult: nil, - expectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - setupMocks: func(c Config, m *mocks, testCase *testCase) { + expectedError: types.NewRPCError(types.DefaultErrorCode, "failed to process unsigned transaction"), + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { + nonce := uint64(7) m.DbTx.On("Rollback", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(uint64(0), errors.New("failed to get last block number")).Once() + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + hasTx := tx != nil + gasMatch := tx.Gas() == uint64(*txArgs.Gas) + toMatch := tx.To().Hex() == txArgs.To.Hex() + gasPriceMatch := tx.GasPrice().Uint64() == gasPrice.Uint64() + valueMatch := tx.Value().Uint64() == value.Uint64() + dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) + nonceMatch := tx.Nonce() == nonce + return hasTx && gasMatch && toMatch && gasPriceMatch && valueMatch && dataMatch && nonceMatch + }) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, nilUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{Err: errors.New("failed to process unsigned transaction")}, nil). + Once() }, }, { - name: "Transaction with all information but failed to process unsigned transaction", - from: common.HexToAddress("0x1"), - to: addressPtr(common.HexToAddress("0x2")), - gas: uint64(24000), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), + name: "Transaction with all information but reverted to process unsigned transaction", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + latest, + }, expectedResult: nil, - expectedError: newRPCError(defaultErrorCode, "failed to process unsigned transaction"), - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(1) + expectedError: types.NewRPCError(types.RevertedErrorCode, "execution reverted"), + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { nonce := uint64(7) m.DbTx.On("Rollback", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumber, nil).Once() - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { + m.State.On("GetLastL2BlockNumber", context.Background(), m.DbTx).Return(blockNumOne.Uint64(), nil).Once() + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) hasTx := tx != nil - gasMatch := tx.Gas() == testCase.gas - toMatch := tx.To().Hex() == testCase.to.Hex() - gasPriceMatch := tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() - valueMatch := tx.Value().Uint64() == testCase.value.Uint64() - dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) + gasMatch := tx.Gas() == uint64(*txArgs.Gas) + toMatch := tx.To().Hex() == txArgs.To.Hex() + gasPriceMatch := tx.GasPrice().Uint64() == gasPrice.Uint64() + valueMatch := tx.Value().Uint64() == value.Uint64() + dataMatch := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) nonceMatch := tx.Nonce() == nonce return hasTx && gasMatch && toMatch && gasPriceMatch && valueMatch && dataMatch && nonceMatch }) - m.State.On("GetNonce", context.Background(), testCase.from, blockNumber, m.DbTx).Return(nonce, nil).Once() - var nilBlockNumber *uint64 - m.State.On("ProcessUnsignedTransaction", context.Background(), txMatchBy, testCase.from, nilBlockNumber, true, m.DbTx).Return(&runtime.ExecutionResult{Err: errors.New("failed to process unsigned transaction")}).Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOneUint64, m.DbTx).Return(block, nil).Once() + m.State.On("GetNonce", context.Background(), *txArgs.From, blockRoot).Return(nonce, nil).Once() + m.State. + On("ProcessUnsignedTransaction", context.Background(), txMatchBy, *txArgs.From, nilUint64, true, m.DbTx). + Return(&runtime.ExecutionResult{Err: runtime.ErrExecutionReverted}, nil). + Once() }, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - msg := ethereum.CallMsg{From: testCase.from, To: testCase.to, Gas: testCase.gas, GasPrice: testCase.gasPrice, Value: testCase.value, Data: testCase.data} - testCase.setupMocks(s.Config, m, testCase) - result, err := c.CallContract(context.Background(), msg, testCase.blockNumber) - assert.Equal(t, testCase.expectedResult, result) - if err != nil || testCase.expectedError != nil { - if expectedErr, ok := testCase.expectedError.(*RPCError); ok { - rpcErr := err.(rpcError) - assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) - assert.Equal(t, expectedErr.Error(), rpcErr.Error()) - } else { - assert.Equal(t, testCase.expectedError, err) - } + res, err := s.JSONRPCCall("eth_call", testCase.params...) + require.NoError(t, err) + + if testCase.expectedResult != nil { + require.NotNil(t, res.Result) + require.Nil(t, res.Error) + + var s string + err = json.Unmarshal(res.Result, &s) + require.NoError(t, err) + + result, err := hex.DecodeHex(s) + require.NoError(t, err) + + assert.Equal(t, testCase.expectedResult, result) + } + + if testCase.expectedError != nil { + expectedErr := testCase.expectedError.(*types.RPCError) + assert.Equal(t, expectedErr.ErrorCode(), res.Error.Code) + assert.Equal(t, expectedErr.Error(), res.Error.Message) } }) } @@ -315,48 +566,50 @@ func TestChainID(t *testing.T) { chainID, err := c.ChainID(context.Background()) require.NoError(t, err) - assert.Equal(t, s.Config.ChainID, chainID.Uint64()) + assert.Equal(t, s.ChainID(), chainID.Uint64()) } func TestEstimateGas(t *testing.T) { - s, m, c := newSequencerMockedServer(t) + s, m, _ := newSequencerMockedServer(t) defer s.Stop() type testCase struct { - name string - from common.Address - to *common.Address - gas uint64 - gasPrice *big.Int - value *big.Int - data []byte - setupMocks func(Config, *mocks, *testCase) - - expectedResult uint64 + name string + params []interface{} + expectedResult *uint64 + expectedError interface{} + setupMocks func(Config, *mocksWrapper, *testCase) } testCases := []testCase{ { - name: "Transaction with all information", - from: common.HexToAddress("0x1"), - to: addressPtr(common.HexToAddress("0x2")), - gas: uint64(24000), - gasPrice: big.NewInt(1), - value: big.NewInt(2), - data: []byte("data"), - expectedResult: 100, - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(10) + name: "Transaction with all information", + params: []interface{}{ + types.TxArgs{ + From: state.HexToAddressPtr("0x1"), + To: state.HexToAddressPtr("0x2"), + Gas: types.ArgUint64Ptr(24000), + GasPrice: types.ArgBytesPtr(big.NewInt(1).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + }, + expectedResult: ptrUint64(100), + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { nonce := uint64(7) - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { if tx == nil { return false } - matchTo := tx.To().Hex() == testCase.to.Hex() - matchGasPrice := tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() - matchValue := tx.Value().Uint64() == testCase.value.Uint64() - matchData := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + + matchTo := tx.To().Hex() == txArgs.To.Hex() + matchGasPrice := tx.GasPrice().Uint64() == gasPrice.Uint64() + matchValue := tx.Value().Uint64() == value.Uint64() + matchData := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) matchNonce := tx.Nonce() == nonce return matchTo && matchGasPrice && matchValue && matchData && matchNonce }) @@ -364,42 +617,44 @@ func TestEstimateGas(t *testing.T) { m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(blockNumber, nil). - Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() m.State. - On("GetNonce", context.Background(), testCase.from, blockNumber, m.DbTx). + On("GetNonce", context.Background(), *txArgs.From, blockRoot). Return(nonce, nil). Once() - - var nilBlockNumber *uint64 m.State. - On("EstimateGas", txMatchBy, testCase.from, nilBlockNumber, m.DbTx). - Return(testCase.expectedResult, nil). + On("EstimateGas", txMatchBy, *txArgs.From, nilUint64, m.DbTx). + Return(*testCase.expectedResult, nil, nil). Once() }, }, { - name: "Transaction without from and gas", - to: addressPtr(common.HexToAddress("0x2")), - gasPrice: big.NewInt(0), - value: big.NewInt(2), - data: []byte("data"), - expectedResult: 100, - setupMocks: func(c Config, m *mocks, testCase *testCase) { - blockNumber := uint64(9) + name: "Transaction without from and gas", + params: []interface{}{ + types.TxArgs{ + To: state.HexToAddressPtr("0x2"), + GasPrice: types.ArgBytesPtr(big.NewInt(0).Bytes()), + Value: types.ArgBytesPtr(big.NewInt(2).Bytes()), + Data: types.ArgBytesPtr([]byte("data")), + }, + }, + expectedResult: ptrUint64(100), + setupMocks: func(c Config, m *mocksWrapper, testCase *testCase) { nonce := uint64(0) - txMatchBy := mock.MatchedBy(func(tx *types.Transaction) bool { + txArgs := testCase.params[0].(types.TxArgs) + txMatchBy := mock.MatchedBy(func(tx *ethTypes.Transaction) bool { if tx == nil { return false } - matchTo := tx.To().Hex() == testCase.to.Hex() - matchGasPrice := tx.GasPrice().Uint64() == testCase.gasPrice.Uint64() - matchValue := tx.Value().Uint64() == testCase.value.Uint64() - matchData := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(testCase.data) + gasPrice := big.NewInt(0).SetBytes(*txArgs.GasPrice) + value := big.NewInt(0).SetBytes(*txArgs.Value) + matchTo := tx.To().Hex() == txArgs.To.Hex() + matchGasPrice := tx.GasPrice().Uint64() == gasPrice.Uint64() + matchValue := tx.Value().Uint64() == value.Uint64() + matchData := hex.EncodeToHex(tx.Data()) == hex.EncodeToHex(*txArgs.Data) matchNonce := tx.Nonce() == nonce return matchTo && matchGasPrice && matchValue && matchData && matchNonce }) @@ -407,15 +662,12 @@ func TestEstimateGas(t *testing.T) { m.DbTx.On("Commit", context.Background()).Return(nil).Once() m.State.On("BeginStateTransaction", context.Background()).Return(m.DbTx, nil).Once() - m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(blockNumber, nil). - Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() - var nilBlockNumber *uint64 m.State. - On("EstimateGas", txMatchBy, common.HexToAddress(c.DefaultSenderAddress), nilBlockNumber, m.DbTx). - Return(testCase.expectedResult, nil). + On("EstimateGas", txMatchBy, common.HexToAddress(DefaultSenderAddress), nilUint64, m.DbTx). + Return(*testCase.expectedResult, nil, nil). Once() }, }, @@ -426,11 +678,27 @@ func TestEstimateGas(t *testing.T) { tc := testCase tc.setupMocks(s.Config, m, &tc) - msg := ethereum.CallMsg{From: testCase.from, To: testCase.to, Gas: testCase.gas, GasPrice: testCase.gasPrice, Value: testCase.value, Data: testCase.data} - result, err := c.EstimateGas(context.Background(), msg) + res, err := s.JSONRPCCall("eth_estimateGas", testCase.params...) require.NoError(t, err) - assert.Equal(t, testCase.expectedResult, result) + if testCase.expectedResult != nil { + require.NotNil(t, res.Result) + require.Nil(t, res.Error) + + var s string + err = json.Unmarshal(res.Result, &s) + require.NoError(t, err) + + result := hex.DecodeUint64(s) + + assert.Equal(t, *testCase.expectedResult, result) + } + + if testCase.expectedError != nil { + expectedErr := testCase.expectedError.(*types.RPCError) + assert.Equal(t, expectedErr.ErrorCode(), res.Error.Code) + assert.Equal(t, expectedErr.Error(), res.Error.Message) + } }) } } @@ -441,19 +709,19 @@ func TestGasPrice(t *testing.T) { testCases := []struct { name string - gasPrice *big.Int + gasPrice uint64 error error expectedGasPrice uint64 }{ - {"GasPrice nil", nil, nil, 0}, - {"GasPrice with value", big.NewInt(50), nil, 50}, - {"failed to get gas price", big.NewInt(50), errors.New("failed to get gas price"), 0}, + {"GasPrice nil", 0, nil, 0}, + {"GasPrice with value", 50, nil, 50}, + {"failed to get gas price", 50, errors.New("failed to get gas price"), 0}, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - m.GasPriceEstimator. - On("GetAvgGasPrice", context.Background()). + m.Pool. + On("GetGasPrice", context.Background()). Return(testCase.gasPrice, testCase.error). Once() @@ -465,28 +733,28 @@ func TestGasPrice(t *testing.T) { } func TestGetBalance(t *testing.T) { - s, m, c := newSequencerMockedServer(t) + s, m, _ := newSequencerMockedServer(t) defer s.Stop() type testCase struct { name string - addr common.Address balance *big.Int - blockNumber *big.Int + params []interface{} expectedBalance uint64 - expectedError *RPCError - setupMocks func(m *mocks, t *testCase) + expectedError *types.RPCError + setupMocks func(m *mocksWrapper, t *testCase) } testCases := []testCase{ { - name: "get balance but failed to get latest block number", - addr: common.HexToAddress("0x123"), - balance: big.NewInt(1000), - blockNumber: nil, + name: "get balance but failed to get latest block number", + balance: big.NewInt(1000), + params: []interface{}{ + addressArg.String(), + }, expectedBalance: 0, - expectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - setupMocks: func(m *mocks, t *testCase) { + expectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), + setupMocks: func(m *mocksWrapper, t *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -498,20 +766,52 @@ func TestGetBalance(t *testing.T) { Once() m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(0), errors.New("failed to get last block number")). + On("GetLastL2Block", context.Background(), m.DbTx). + Return(nil, errors.New("failed to get last block number")).Once() + }, + }, + { + name: "get balance for block nil", + params: []interface{}{ + addressArg.String(), + }, + balance: big.NewInt(1000), + expectedBalance: 1000, + expectedError: nil, + setupMocks: func(m *mocksWrapper, t *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State. + On("GetLastL2Block", context.Background(), m.DbTx). + Return(block, nil).Once() + + m.State. + On("GetBalance", context.Background(), addressArg, blockRoot). + Return(t.balance, nil). Once() }, }, { - name: "get balance for block nil", - addr: common.HexToAddress("0x123"), + name: "get balance for block by hash with EIP-1898", + params: []interface{}{ + addressArg.String(), + map[string]interface{}{ + types.BlockHashKey: blockHash.String(), + }, + }, balance: big.NewInt(1000), - blockNumber: nil, expectedBalance: 1000, expectedError: nil, - setupMocks: func(m *mocks, t *testCase) { - const lastBlockNumber = uint64(10) + setupMocks: func(m *mocksWrapper, t *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -522,26 +822,27 @@ func TestGetBalance(t *testing.T) { Return(m.DbTx, nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(lastBlockNumber, nil). + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil). Once() m.State. - On("GetBalance", context.Background(), t.addr, lastBlockNumber, m.DbTx). + On("GetBalance", context.Background(), addressArg, blockRoot). Return(t.balance, nil). Once() }, }, { - name: "get balance for not found result", - addr: common.HexToAddress("0x123"), + name: "get balance for not found result", + params: []interface{}{ + addressArg.String(), + }, balance: big.NewInt(1000), - blockNumber: nil, expectedBalance: 0, expectedError: nil, - setupMocks: func(m *mocks, t *testCase) { - const lastBlockNumber = uint64(10) + setupMocks: func(m *mocksWrapper, t *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -552,26 +853,24 @@ func TestGetBalance(t *testing.T) { Return(m.DbTx, nil). Once() - m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(lastBlockNumber, nil). - Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() m.State. - On("GetBalance", context.Background(), t.addr, lastBlockNumber, m.DbTx). + On("GetBalance", context.Background(), addressArg, blockRoot). Return(big.NewInt(0), state.ErrNotFound). Once() }, }, { - name: "get balance with state failure", - addr: common.HexToAddress("0x123"), + name: "get balance with state failure", + params: []interface{}{ + addressArg.String(), + }, balance: big.NewInt(1000), - blockNumber: nil, expectedBalance: 0, - expectedError: newRPCError(defaultErrorCode, "failed to get balance from state"), - setupMocks: func(m *mocks, t *testCase) { - const lastBlockNumber = uint64(10) + expectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get balance from state"), + setupMocks: func(m *mocksWrapper, t *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -582,13 +881,11 @@ func TestGetBalance(t *testing.T) { Return(m.DbTx, nil). Once() - m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(lastBlockNumber, nil). - Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() m.State. - On("GetBalance", context.Background(), t.addr, lastBlockNumber, m.DbTx). + On("GetBalance", context.Background(), addressArg, blockRoot). Return(nil, errors.New("failed to get balance")). Once() }, @@ -599,12 +896,26 @@ func TestGetBalance(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { tc := testCase testCase.setupMocks(m, &tc) - balance, err := c.BalanceAt(context.Background(), tc.addr, tc.blockNumber) - assert.Equal(t, tc.expectedBalance, balance.Uint64()) - if err != nil || tc.expectedError != nil { - rpcErr := err.(rpcError) - assert.Equal(t, tc.expectedError.ErrorCode(), rpcErr.ErrorCode()) - assert.Equal(t, tc.expectedError.Error(), rpcErr.Error()) + + res, err := s.JSONRPCCall("eth_getBalance", tc.params...) + require.NoError(t, err) + + if tc.expectedBalance != 0 { + require.NotNil(t, res.Result) + require.Nil(t, res.Error) + + var balanceStr string + err = json.Unmarshal(res.Result, &balanceStr) + require.NoError(t, err) + + balance := new(big.Int) + balance.SetString(balanceStr, 0) + assert.Equal(t, tc.expectedBalance, balance.Uint64()) + } + + if tc.expectedError != nil { + assert.Equal(t, tc.expectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.expectedError.Error(), res.Error.Message) } }) } @@ -614,9 +925,9 @@ func TestGetL2BlockByHash(t *testing.T) { type testCase struct { Name string Hash common.Hash - ExpectedResult *types.Block + ExpectedResult *ethTypes.Block ExpectedError interface{} - SetupMocks func(*mocks, *testCase) + SetupMocks func(*mocksWrapper, *testCase) } testCases := []testCase{ @@ -625,7 +936,7 @@ func TestGetL2BlockByHash(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -645,8 +956,8 @@ func TestGetL2BlockByHash(t *testing.T) { Name: "Failed get block from state", Hash: common.HexToHash("0x234"), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get block by hash from state"), - SetupMocks: func(m *mocks, tc *testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get block by hash from state"), + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -666,16 +977,16 @@ func TestGetL2BlockByHash(t *testing.T) { { Name: "get block successfully", Hash: common.HexToHash("0x345"), - ExpectedResult: types.NewBlock( - &types.Header{Number: big.NewInt(1), UncleHash: types.EmptyUncleHash, Root: types.EmptyRootHash}, - []*types.Transaction{types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, + ExpectedResult: ethTypes.NewBlock( + ðTypes.Header{Number: big.NewInt(1), UncleHash: ethTypes.EmptyUncleHash, Root: ethTypes.EmptyRootHash}, + []*ethTypes.Transaction{ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, nil, - []*types.Receipt{types.NewReceipt([]byte{}, false, uint64(0))}, + []*ethTypes.Receipt{ethTypes.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}, ), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { - block := types.NewBlock(types.CopyHeader(tc.ExpectedResult.Header()), tc.ExpectedResult.Transactions(), tc.ExpectedResult.Uncles(), []*types.Receipt{types.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}) + SetupMocks: func(m *mocksWrapper, tc *testCase) { + block := ethTypes.NewBlock(ethTypes.CopyHeader(tc.ExpectedResult.Header()), tc.ExpectedResult.Transactions(), tc.ExpectedResult.Uncles(), []*ethTypes.Receipt{ethTypes.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}) m.DbTx. On("Commit", context.Background()). @@ -712,8 +1023,8 @@ func TestGetL2BlockByHash(t *testing.T) { } if err != nil || tc.ExpectedError != nil { - if expectedErr, ok := tc.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := tc.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -728,9 +1039,9 @@ func TestGetL2BlockByNumber(t *testing.T) { type testCase struct { Name string Number *big.Int - ExpectedResult *types.Block + ExpectedResult *ethTypes.Block ExpectedError interface{} - SetupMocks func(*mocks, *testCase) + SetupMocks func(*mocksWrapper, *testCase) } testCases := []testCase{ @@ -739,7 +1050,7 @@ func TestGetL2BlockByNumber(t *testing.T) { Number: big.NewInt(123), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -758,17 +1069,17 @@ func TestGetL2BlockByNumber(t *testing.T) { { Name: "get specific block successfully", Number: big.NewInt(345), - ExpectedResult: types.NewBlock( - &types.Header{Number: big.NewInt(1), UncleHash: types.EmptyUncleHash, Root: types.EmptyRootHash}, - []*types.Transaction{types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, + ExpectedResult: ethTypes.NewBlock( + ðTypes.Header{Number: big.NewInt(1), UncleHash: ethTypes.EmptyUncleHash, Root: ethTypes.EmptyRootHash}, + []*ethTypes.Transaction{ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, nil, - []*types.Receipt{types.NewReceipt([]byte{}, false, uint64(0))}, + []*ethTypes.Receipt{ethTypes.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}, ), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { - block := types.NewBlock(types.CopyHeader(tc.ExpectedResult.Header()), tc.ExpectedResult.Transactions(), - tc.ExpectedResult.Uncles(), []*types.Receipt{types.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}) + SetupMocks: func(m *mocksWrapper, tc *testCase) { + block := ethTypes.NewBlock(ethTypes.CopyHeader(tc.ExpectedResult.Header()), tc.ExpectedResult.Transactions(), + tc.ExpectedResult.Uncles(), []*ethTypes.Receipt{ethTypes.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}) m.DbTx. On("Commit", context.Background()). @@ -789,15 +1100,15 @@ func TestGetL2BlockByNumber(t *testing.T) { { Name: "get latest block successfully", Number: nil, - ExpectedResult: types.NewBlock( - &types.Header{Number: big.NewInt(2), UncleHash: types.EmptyUncleHash, Root: types.EmptyRootHash}, - []*types.Transaction{types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, + ExpectedResult: ethTypes.NewBlock( + ðTypes.Header{Number: big.NewInt(2), UncleHash: ethTypes.EmptyUncleHash, Root: ethTypes.EmptyRootHash}, + []*ethTypes.Transaction{ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})}, nil, - []*types.Receipt{types.NewReceipt([]byte{}, false, uint64(0))}, + []*ethTypes.Receipt{ethTypes.NewReceipt([]byte{}, false, uint64(0))}, &trie.StackTrie{}, ), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -823,8 +1134,8 @@ func TestGetL2BlockByNumber(t *testing.T) { Name: "get latest block fails to compute block number", Number: nil, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc *testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -845,8 +1156,8 @@ func TestGetL2BlockByNumber(t *testing.T) { Name: "get latest block fails to load block by number", Number: nil, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "couldn't load block from state by number 1"), - SetupMocks: func(m *mocks, tc *testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "couldn't load block from state by number 1"), + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -871,16 +1182,16 @@ func TestGetL2BlockByNumber(t *testing.T) { { Name: "get pending block successfully", Number: big.NewInt(-1), - ExpectedResult: types.NewBlock(&types.Header{Number: big.NewInt(2)}, nil, nil, nil, &trie.StackTrie{}), + ExpectedResult: ethTypes.NewBlock(ðTypes.Header{Number: big.NewInt(2)}, nil, nil, nil, &trie.StackTrie{}), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { - lastBlockHeader := types.CopyHeader(tc.ExpectedResult.Header()) + SetupMocks: func(m *mocksWrapper, tc *testCase) { + lastBlockHeader := ethTypes.CopyHeader(tc.ExpectedResult.Header()) lastBlockHeader.Number.Sub(lastBlockHeader.Number, big.NewInt(1)) - lastBlock := types.NewBlock(lastBlockHeader, nil, nil, nil, &trie.StackTrie{}) + lastBlock := ethTypes.NewBlock(lastBlockHeader, nil, nil, nil, &trie.StackTrie{}) - expectedResultHeader := types.CopyHeader(tc.ExpectedResult.Header()) + expectedResultHeader := ethTypes.CopyHeader(tc.ExpectedResult.Header()) expectedResultHeader.ParentHash = lastBlock.Hash() - tc.ExpectedResult = types.NewBlock(expectedResultHeader, nil, nil, nil, &trie.StackTrie{}) + tc.ExpectedResult = ethTypes.NewBlock(expectedResultHeader, nil, nil, nil, &trie.StackTrie{}) m.DbTx. On("Commit", context.Background()). @@ -902,8 +1213,8 @@ func TestGetL2BlockByNumber(t *testing.T) { Name: "get pending block fails", Number: big.NewInt(-1), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "couldn't load last block from state to compute the pending block"), - SetupMocks: func(m *mocks, tc *testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "couldn't load last block from state to compute the pending block"), + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -946,8 +1257,8 @@ func TestGetL2BlockByNumber(t *testing.T) { } if err != nil || tc.ExpectedError != nil { - if expectedErr, ok := tc.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := tc.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -1005,7 +1316,7 @@ func TestGetUncleCountByBlockHash(t *testing.T) { assert.Equal(t, "2.0", res.JSONRPC) assert.Nil(t, res.Error) - var result argUint64 + var result types.ArgUint64 err = json.Unmarshal(res.Result, &result) require.NoError(t, err) @@ -1023,7 +1334,7 @@ func TestGetUncleCountByBlockNumber(t *testing.T) { assert.Equal(t, "2.0", res.JSONRPC) assert.Nil(t, res.Error) - var result argUint64 + var result types.ArgUint64 err = json.Unmarshal(res.Result, &result) require.NoError(t, err) @@ -1031,28 +1342,28 @@ func TestGetUncleCountByBlockNumber(t *testing.T) { } func TestGetCode(t *testing.T) { - s, m, c := newSequencerMockedServer(t) + s, m, _ := newSequencerMockedServer(t) defer s.Stop() type testCase struct { Name string - Addr common.Address - BlockNumber *big.Int + Params []interface{} ExpectedResult []byte ExpectedError interface{} - SetupMocks func(m *mocks, tc *testCase) + SetupMocks func(m *mocksWrapper, tc *testCase) } testCases := []testCase{ { - Name: "failed to identify the block", - Addr: common.HexToAddress("0x123"), - BlockNumber: nil, + Name: "failed to identify the block", + Params: []interface{}{ + addressArg.String(), + }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1064,19 +1375,21 @@ func TestGetCode(t *testing.T) { Once() m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(0), errors.New("failed to get last block number")). + On("GetLastL2Block", context.Background(), m.DbTx). + Return(nil, errors.New("failed to get last block number")). Once() }, }, { - Name: "failed to get code", - Addr: common.HexToAddress("0x123"), - BlockNumber: big.NewInt(1), + Name: "failed to get code", + Params: []interface{}{ + addressArg.String(), + map[string]interface{}{types.BlockNumberKey: hex.EncodeBig(blockNumOne)}, + }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get code"), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get code"), - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1087,20 +1400,25 @@ func TestGetCode(t *testing.T) { Return(m.DbTx, nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetCode", context.Background(), tc.Addr, tc.BlockNumber.Uint64(), m.DbTx). + On("GetCode", context.Background(), addressArg, blockRoot). Return(nil, errors.New("failed to get code")). Once() }, }, { - Name: "code not found", - Addr: common.HexToAddress("0x123"), - BlockNumber: big.NewInt(1), + Name: "code not found", + Params: []interface{}{ + addressArg.String(), + map[string]interface{}{types.BlockNumberKey: hex.EncodeBig(blockNumOne)}, + }, ExpectedResult: []byte{}, ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1111,20 +1429,53 @@ func TestGetCode(t *testing.T) { Return(m.DbTx, nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetCode", context.Background(), tc.Addr, tc.BlockNumber.Uint64(), m.DbTx). + On("GetCode", context.Background(), addressArg, blockRoot). Return(nil, state.ErrNotFound). Once() }, }, { - Name: "get code successfully", - Addr: common.HexToAddress("0x123"), - BlockNumber: big.NewInt(1), + Name: "get code successfully", + Params: []interface{}{ + addressArg.String(), + map[string]interface{}{types.BlockNumberKey: hex.EncodeBig(blockNumOne)}, + }, ExpectedResult: []byte{1, 2, 3}, ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumOne, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumOne.Uint64(), m.DbTx).Return(block, nil).Once() + + m.State. + On("GetCode", context.Background(), addressArg, blockRoot). + Return(tc.ExpectedResult, nil). + Once() + }, + }, + { + Name: "get code successfully by block hash with EIP-1898", + Params: []interface{}{ + addressArg.String(), + map[string]interface{}{types.BlockHashKey: blockHash.String()}, + }, + ExpectedResult: []byte{1, 2, 3}, + ExpectedError: nil, + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1135,8 +1486,14 @@ func TestGetCode(t *testing.T) { Return(m.DbTx, nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State. + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil). + Once() + m.State. - On("GetCode", context.Background(), tc.Addr, tc.BlockNumber.Uint64(), m.DbTx). + On("GetCode", context.Background(), addressArg, blockRoot). Return(tc.ExpectedResult, nil). Once() }, @@ -1147,14 +1504,27 @@ func TestGetCode(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { tc := testCase tc.SetupMocks(m, &tc) - result, err := c.CodeAt(context.Background(), tc.Addr, tc.BlockNumber) - assert.Equal(t, tc.ExpectedResult, result) - if err != nil || tc.ExpectedError != nil { - if expectedErr, ok := tc.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) - assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) - assert.Equal(t, expectedErr.Error(), rpcErr.Error()) + res, err := s.JSONRPCCall("eth_getCode", tc.Params...) + require.NoError(t, err) + + if tc.ExpectedResult != nil { + require.NotNil(t, res.Result) + require.Nil(t, res.Error) + + var codeStr string + err = json.Unmarshal(res.Result, &codeStr) + require.NoError(t, err) + + code, err := hex.DecodeString(codeStr[2:]) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, code) + } + + if tc.ExpectedError != nil { + if expectedErr, ok := tc.ExpectedError.(*types.RPCError); ok { + assert.Equal(t, expectedErr.ErrorCode(), res.Error.Code) + assert.Equal(t, expectedErr.Error(), res.Error.Message) } else { assert.Equal(t, tc.ExpectedError, err) } @@ -1164,30 +1534,29 @@ func TestGetCode(t *testing.T) { } func TestGetStorageAt(t *testing.T) { - s, m, c := newSequencerMockedServer(t) + s, m, _ := newSequencerMockedServer(t) defer s.Stop() type testCase struct { Name string - Addr common.Address - Key common.Hash - BlockNumber *big.Int + Params []interface{} ExpectedResult []byte - ExpectedError interface{} + ExpectedError *types.RPCError - SetupMocks func(m *mocks, tc *testCase) + SetupMocks func(m *mocksWrapper, tc *testCase) } testCases := []testCase{ { - Name: "failed to identify the block", - Addr: common.HexToAddress("0x123"), - Key: common.HexToHash("0x123"), - BlockNumber: nil, + Name: "failed to identify the block", + Params: []interface{}{ + addressArg.String(), + keyArg.String(), + }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1199,20 +1568,24 @@ func TestGetStorageAt(t *testing.T) { Once() m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(0), errors.New("failed to get last block number")). + On("GetLastL2Block", context.Background(), m.DbTx). + Return(nil, errors.New("failed to get last block number")). Once() }, }, { - Name: "failed to get storage at", - Addr: common.HexToAddress("0x123"), - Key: common.HexToHash("0x123"), - BlockNumber: big.NewInt(1), + Name: "failed to get storage at", + Params: []interface{}{ + addressArg.String(), + keyArg.String(), + map[string]interface{}{ + types.BlockNumberKey: hex.EncodeBig(blockNumOne), + }, + }, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get storage value from state"), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get storage value from state"), - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1223,21 +1596,29 @@ func TestGetStorageAt(t *testing.T) { Return(m.DbTx, nil). Once() + blockNumber := big.NewInt(1) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumber, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumber.Uint64(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetStorageAt", context.Background(), tc.Addr, tc.Key.Big(), tc.BlockNumber.Uint64(), m.DbTx). + On("GetStorageAt", context.Background(), addressArg, keyArg.Big(), blockRoot). Return(nil, errors.New("failed to get storage at")). Once() }, }, { - Name: "code not found", - Addr: common.HexToAddress("0x123"), - Key: common.HexToHash("0x123"), - BlockNumber: big.NewInt(1), + Name: "code not found", + Params: []interface{}{ + addressArg.String(), + keyArg.String(), + map[string]interface{}{ + types.BlockNumberKey: hex.EncodeBig(blockNumOne), + }, + }, ExpectedResult: common.Hash{}.Bytes(), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1248,21 +1629,29 @@ func TestGetStorageAt(t *testing.T) { Return(m.DbTx, nil). Once() + blockNumber := big.NewInt(1) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumber, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumber.Uint64(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetStorageAt", context.Background(), tc.Addr, tc.Key.Big(), tc.BlockNumber.Uint64(), m.DbTx). + On("GetStorageAt", context.Background(), addressArg, keyArg.Big(), blockRoot). Return(nil, state.ErrNotFound). Once() }, }, { - Name: "get code successfully", - Addr: common.HexToAddress("0x123"), - Key: common.HexToHash("0x123"), - BlockNumber: big.NewInt(1), + Name: "get code successfully", + Params: []interface{}{ + addressArg.String(), + keyArg.String(), + map[string]interface{}{ + types.BlockNumberKey: hex.EncodeBig(blockNumOne), + }, + }, ExpectedResult: common.BigToHash(big.NewInt(123)).Bytes(), ExpectedError: nil, - SetupMocks: func(m *mocks, tc *testCase) { + SetupMocks: func(m *mocksWrapper, tc *testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1273,8 +1662,47 @@ func TestGetStorageAt(t *testing.T) { Return(m.DbTx, nil). Once() + blockNumber := big.NewInt(1) + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumber, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumber.Uint64(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetStorageAt", context.Background(), tc.Addr, tc.Key.Big(), tc.BlockNumber.Uint64(), m.DbTx). + On("GetStorageAt", context.Background(), addressArg, keyArg.Big(), blockRoot). + Return(big.NewInt(123), nil). + Once() + }, + }, + { + Name: "get code by block hash successfully with EIP-1898", + Params: []interface{}{ + addressArg.String(), + keyArg.String(), + map[string]interface{}{ + types.BlockHashKey: blockHash.String(), + }, + }, + ExpectedResult: common.BigToHash(big.NewInt(123)).Bytes(), + ExpectedError: nil, + + SetupMocks: func(m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State. + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil). + Once() + + m.State. + On("GetStorageAt", context.Background(), addressArg, keyArg.Big(), blockRoot). Return(big.NewInt(123), nil). Once() }, @@ -1285,17 +1713,21 @@ func TestGetStorageAt(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { tc := testCase tc.SetupMocks(m, &tc) - result, err := c.StorageAt(context.Background(), tc.Addr, tc.Key, tc.BlockNumber) - assert.Equal(t, tc.ExpectedResult, result) + res, err := s.JSONRPCCall("eth_getStorageAt", tc.Params...) + require.NoError(t, err) + if tc.ExpectedResult != nil { + require.NotNil(t, res.Result) + require.Nil(t, res.Error) - if err != nil || tc.ExpectedError != nil { - if expectedErr, ok := tc.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) - assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) - assert.Equal(t, expectedErr.Error(), rpcErr.Error()) - } else { - assert.Equal(t, tc.ExpectedError, err) - } + var storage common.Hash + err = json.Unmarshal(res.Result, &storage) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, storage.Bytes()) + } + + if tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) } }) } @@ -1326,16 +1758,37 @@ func TestSyncing(t *testing.T) { type testCase struct { Name string ExpectedResult *ethereum.SyncProgress - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ + { + Name: "failed to get last l2 block number", + ExpectedResult: nil, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get last block number from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(0), errors.New("failed to get last l2 block number from state")). + Once() + }, + }, { Name: "failed to get syncing information", ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get syncing info from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get syncing info from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1346,6 +1799,11 @@ func TestSyncing(t *testing.T) { Return(m.DbTx, nil). Once() + m.State. + On("GetLastL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + m.State. On("GetSyncingInfo", context.Background(), m.DbTx). Return(state.SyncingInfo{}, errors.New("failed to get syncing info from state")). @@ -1356,7 +1814,7 @@ func TestSyncing(t *testing.T) { Name: "get syncing information successfully while syncing", ExpectedResult: ðereum.SyncProgress{StartingBlock: 1, CurrentBlock: 2, HighestBlock: 3}, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1367,6 +1825,11 @@ func TestSyncing(t *testing.T) { Return(m.DbTx, nil). Once() + m.State. + On("GetLastL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + m.State. On("GetSyncingInfo", context.Background(), m.DbTx). Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 2, LastBlockNumberSeen: 3, LastBlockNumberConsolidated: 3}, nil). @@ -1377,7 +1840,7 @@ func TestSyncing(t *testing.T) { Name: "get syncing information successfully when synced", ExpectedResult: nil, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1388,6 +1851,11 @@ func TestSyncing(t *testing.T) { Return(m.DbTx, nil). Once() + m.State. + On("GetLastL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + m.State. On("GetSyncingInfo", context.Background(), m.DbTx). Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 1, LastBlockNumberSeen: 1, LastBlockNumberConsolidated: 1}, nil). @@ -1408,8 +1876,8 @@ func TestSyncing(t *testing.T) { } if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -1429,9 +1897,9 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Hash common.Hash Index uint - ExpectedResult *types.Transaction + ExpectedResult *ethTypes.Transaction ExpectedError interface{} - SetupMocks func(m *mocks, tc testCase) + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ @@ -1439,9 +1907,9 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Name: "Get Tx Successfully", Hash: common.HexToHash("0x999"), Index: uint(1), - ExpectedResult: types.NewTransaction(1, common.HexToAddress("0x111"), big.NewInt(2), 3, big.NewInt(4), []byte{5, 6, 7, 8}), + ExpectedResult: ethTypes.NewTransaction(1, common.HexToAddress("0x111"), big.NewInt(2), 3, big.NewInt(4), []byte{5, 6, 7, 8}), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { tx := tc.ExpectedResult m.DbTx. On("Commit", context.Background()). @@ -1458,7 +1926,7 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Return(tx, nil). Once() - receipt := types.NewReceipt([]byte{}, false, 0) + receipt := ethTypes.NewReceipt([]byte{}, false, 0) receipt.BlockHash = common.Hash{} receipt.BlockNumber = big.NewInt(1) receipt.TransactionIndex = tc.Index @@ -1475,7 +1943,7 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Index: uint(1), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1497,8 +1965,8 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Hash: common.HexToHash("0x999"), Index: uint(1), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get transaction"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get transaction"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1521,8 +1989,8 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Index: uint(1), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc testCase) { - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ethTypes.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1549,9 +2017,9 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { Hash: common.HexToHash("0x999"), Index: uint(1), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get transaction receipt"), - SetupMocks: func(m *mocks, tc testCase) { - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get transaction receipt"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ethTypes.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1587,8 +2055,8 @@ func TestGetTransactionL2onByBlockHashAndIndex(t *testing.T) { } if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -1608,9 +2076,9 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { BlockNumber string Index uint - ExpectedResult *types.Transaction - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedResult *ethTypes.Transaction + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ @@ -1618,9 +2086,9 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { Name: "Get Tx Successfully", BlockNumber: "0x1", Index: uint(0), - ExpectedResult: types.NewTransaction(1, common.HexToAddress("0x111"), big.NewInt(2), 3, big.NewInt(4), []byte{5, 6, 7, 8}), + ExpectedResult: ethTypes.NewTransaction(1, common.HexToAddress("0x111"), big.NewInt(2), 3, big.NewInt(4), []byte{5, 6, 7, 8}), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { tx := tc.ExpectedResult blockNumber, _ := encoding.DecodeUint64orHex(&tc.BlockNumber) m.DbTx. @@ -1638,7 +2106,7 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { Return(tx, nil). Once() - receipt := types.NewReceipt([]byte{}, false, 0) + receipt := ethTypes.NewReceipt([]byte{}, false, 0) receipt.BlockHash = common.Hash{} receipt.BlockNumber = big.NewInt(1) receipt.TransactionIndex = tc.Index @@ -1650,11 +2118,11 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { }, { Name: "failed to identify block number", - BlockNumber: "latest", + BlockNumber: latest, Index: uint(0), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1677,7 +2145,7 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { Index: uint(0), ExpectedResult: nil, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { blockNumber, _ := encoding.DecodeUint64orHex(&tc.BlockNumber) m.DbTx. On("Commit", context.Background()). @@ -1700,8 +2168,8 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { BlockNumber: "0x1", Index: uint(0), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get transaction"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get transaction"), + SetupMocks: func(m *mocksWrapper, tc testCase) { blockNumber, _ := encoding.DecodeUint64orHex(&tc.BlockNumber) m.DbTx. On("Rollback", context.Background()). @@ -1725,8 +2193,8 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { Index: uint(0), ExpectedResult: nil, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ethTypes.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) blockNumber, _ := encoding.DecodeUint64orHex(&tc.BlockNumber) m.DbTx. @@ -1755,9 +2223,9 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { BlockNumber: "0x1", Index: uint(0), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get transaction receipt"), - SetupMocks: func(m *mocks, tc testCase) { - tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get transaction receipt"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ethTypes.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), []byte{}) blockNumber, _ := encoding.DecodeUint64orHex(&tc.BlockNumber) m.DbTx. @@ -1799,7 +2267,7 @@ func TestGetTransactionByBlockNumberAndIndex(t *testing.T) { require.NoError(t, err) if result != nil || testCase.ExpectedResult != nil { - var tx types.Transaction + var tx ethTypes.Transaction err = json.Unmarshal(res.Result, &tx) require.NoError(t, err) assert.Equal(t, testCase.ExpectedResult.Hash(), tx.Hash()) @@ -1822,9 +2290,9 @@ func TestGetTransactionByHash(t *testing.T) { Name string Hash common.Hash ExpectedPending bool - ExpectedResult *types.Transaction + ExpectedResult *ethTypes.Transaction ExpectedError interface{} - SetupMocks func(m *mocks, tc testCase) + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ @@ -1832,9 +2300,9 @@ func TestGetTransactionByHash(t *testing.T) { Name: "Get TX Successfully from state", Hash: common.HexToHash("0x123"), ExpectedPending: false, - ExpectedResult: types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}), + ExpectedResult: ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1850,7 +2318,7 @@ func TestGetTransactionByHash(t *testing.T) { Return(tc.ExpectedResult, nil). Once() - receipt := types.NewReceipt([]byte{}, false, 0) + receipt := ethTypes.NewReceipt([]byte{}, false, 0) receipt.BlockHash = common.Hash{} receipt.BlockNumber = big.NewInt(1) @@ -1864,9 +2332,9 @@ func TestGetTransactionByHash(t *testing.T) { Name: "Get TX Successfully from pool", Hash: common.HexToHash("0x123"), ExpectedPending: true, - ExpectedResult: types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}), + ExpectedResult: ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1894,7 +2362,7 @@ func TestGetTransactionByHash(t *testing.T) { ExpectedPending: false, ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -1912,7 +2380,7 @@ func TestGetTransactionByHash(t *testing.T) { m.Pool. On("GetTxByHash", context.Background(), tc.Hash). - Return(nil, pgpoolstorage.ErrNotFound). + Return(nil, pool.ErrNotFound). Once() }, }, @@ -1921,8 +2389,8 @@ func TestGetTransactionByHash(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedPending: false, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to load transaction by hash from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to load transaction by hash from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1944,8 +2412,8 @@ func TestGetTransactionByHash(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedPending: false, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to load transaction by hash from pool"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to load transaction by hash from pool"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -1972,9 +2440,9 @@ func TestGetTransactionByHash(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedPending: false, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "transaction receipt not found"), - SetupMocks: func(m *mocks, tc testCase) { - tx := &types.Transaction{} + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "transaction receipt not found"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ðTypes.Transaction{} m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2001,9 +2469,9 @@ func TestGetTransactionByHash(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedPending: false, ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to load transaction receipt from state"), - SetupMocks: func(m *mocks, tc testCase) { - tx := &types.Transaction{} + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to load transaction receipt from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + tx := ðTypes.Transaction{} m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2040,8 +2508,8 @@ func TestGetTransactionByHash(t *testing.T) { } if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2061,16 +2529,16 @@ func TestGetBlockTransactionCountByHash(t *testing.T) { BlockHash common.Hash ExpectedResult uint ExpectedError interface{} - SetupMocks func(m *mocks, tc testCase) + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Count txs successfully", - BlockHash: common.HexToHash("0x123"), + BlockHash: blockHash, ExpectedResult: uint(10), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2089,10 +2557,10 @@ func TestGetBlockTransactionCountByHash(t *testing.T) { }, { Name: "Failed to count txs by hash", - BlockHash: common.HexToHash("0x123"), + BlockHash: blockHash, ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to count transactions"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to count transactions"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2120,8 +2588,8 @@ func TestGetBlockTransactionCountByHash(t *testing.T) { assert.Equal(t, testCase.ExpectedResult, result) if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2140,17 +2608,17 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { Name string BlockNumber string ExpectedResult uint - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Count txs successfully for latest block", - BlockNumber: "latest", + BlockNumber: latest, ExpectedResult: uint(10), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { blockNumber := uint64(10) m.DbTx. On("Commit", context.Background()). @@ -2178,7 +2646,7 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { BlockNumber: "pending", ExpectedResult: uint(10), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2197,10 +2665,10 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { }, { Name: "failed to get last block number", - BlockNumber: "latest", + BlockNumber: latest, ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2219,10 +2687,10 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { }, { Name: "failed to count tx", - BlockNumber: "latest", + BlockNumber: latest, ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to count transactions"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to count transactions"), + SetupMocks: func(m *mocksWrapper, tc testCase) { blockNumber := uint64(10) m.DbTx. On("Rollback", context.Background()). @@ -2249,8 +2717,8 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { Name: "failed to count pending tx", BlockNumber: "pending", ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to count pending transactions"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to count pending transactions"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2280,7 +2748,7 @@ func TestGetBlockTransactionCountByNumber(t *testing.T) { assert.Equal(t, "2.0", res.JSONRPC) if res.Result != nil { - var result argUint64 + var result types.ArgUint64 err = json.Unmarshal(res.Result, &result) require.NoError(t, err) assert.Equal(t, testCase.ExpectedResult, uint(result)) @@ -2300,23 +2768,19 @@ func TestGetTransactionCount(t *testing.T) { type testCase struct { Name string - Address string - BlockNumber string + Params []interface{} ExpectedResult uint - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Count txs successfully", - Address: common.HexToAddress("0x123").Hex(), - BlockNumber: "latest", + Params: []interface{}{addressArg.String()}, ExpectedResult: uint(10), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { - blockNumber := uint64(10) - address := common.HexToAddress(tc.Address) + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2327,26 +2791,55 @@ func TestGetTransactionCount(t *testing.T) { Return(m.DbTx, nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetLastL2Block", context.Background(), m.DbTx).Return(block, nil).Once() + m.State. - On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(blockNumber, nil). + On("GetNonce", context.Background(), addressArg, blockRoot). + Return(uint64(10), nil). + Once() + }, + }, + { + Name: "Count txs successfully by block hash with EIP-1898", + Params: []interface{}{ + addressArg.String(), + map[string]interface{}{types.BlockHashKey: blockHash.String()}, + }, + ExpectedResult: uint(10), + ExpectedError: nil, + SetupMocks: func(m *mocksWrapper, tc testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State. + On("GetL2BlockByHash", context.Background(), blockHash, m.DbTx). + Return(block, nil). Once() m.State. - On("GetNonce", context.Background(), address, blockNumber, m.DbTx). + On("GetNonce", context.Background(), addressArg, blockRoot). Return(uint64(10), nil). Once() }, }, { - Name: "Count txs nonce not found", - Address: common.HexToAddress("0x123").Hex(), - BlockNumber: "latest", + Name: "Count txs nonce not found", + Params: []interface{}{ + addressArg.String(), + latest, + }, ExpectedResult: 0, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { - blockNumber := uint64(10) - address := common.HexToAddress(tc.Address) + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2359,22 +2852,27 @@ func TestGetTransactionCount(t *testing.T) { m.State. On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(blockNumber, nil). + Return(blockNumTen.Uint64(), nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumTenUint64, m.DbTx).Return(block, nil).Once() + m.State. - On("GetNonce", context.Background(), address, blockNumber, m.DbTx). + On("GetNonce", context.Background(), addressArg, blockRoot). Return(uint64(0), state.ErrNotFound). Once() }, }, { - Name: "failed to get last block number", - Address: common.HexToAddress("0x123").Hex(), - BlockNumber: "latest", + Name: "failed to get last block number", + Params: []interface{}{ + addressArg.String(), + latest, + }, ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to get the last block number from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2392,14 +2890,14 @@ func TestGetTransactionCount(t *testing.T) { }, }, { - Name: "failed to get nonce", - Address: common.HexToAddress("0x123").Hex(), - BlockNumber: "latest", + Name: "failed to get nonce", + Params: []interface{}{ + addressArg.String(), + latest, + }, ExpectedResult: 0, - ExpectedError: newRPCError(defaultErrorCode, "failed to count transactions"), - SetupMocks: func(m *mocks, tc testCase) { - blockNumber := uint64(10) - address := common.HexToAddress(tc.Address) + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to count transactions"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2412,11 +2910,14 @@ func TestGetTransactionCount(t *testing.T) { m.State. On("GetLastL2BlockNumber", context.Background(), m.DbTx). - Return(blockNumber, nil). + Return(blockNumTen.Uint64(), nil). Once() + block := ethTypes.NewBlockWithHeader(ðTypes.Header{Number: blockNumTen, Root: blockRoot}) + m.State.On("GetL2BlockByNumber", context.Background(), blockNumTenUint64, m.DbTx).Return(block, nil).Once() + m.State. - On("GetNonce", context.Background(), address, blockNumber, m.DbTx). + On("GetNonce", context.Background(), addressArg, blockRoot). Return(uint64(0), errors.New("failed to get nonce")). Once() }, @@ -2427,14 +2928,14 @@ func TestGetTransactionCount(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { tc := testCase tc.SetupMocks(m, tc) - res, err := s.JSONRPCCall("eth_getTransactionCount", tc.Address, tc.BlockNumber) + res, err := s.JSONRPCCall("eth_getTransactionCount", tc.Params...) require.NoError(t, err) assert.Equal(t, float64(1), res.ID) assert.Equal(t, "2.0", res.JSONRPC) if res.Result != nil { - var result argUint64 + var result types.ArgUint64 err = json.Unmarshal(res.Result, &result) require.NoError(t, err) assert.Equal(t, testCase.ExpectedResult, uint(result)) @@ -2455,18 +2956,18 @@ func TestGetTransactionReceipt(t *testing.T) { type testCase struct { Name string Hash common.Hash - ExpectedResult *types.Receipt + ExpectedResult *ethTypes.Receipt ExpectedError interface{} - SetupMocks func(m *mocks, tc testCase) + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Get TX receipt Successfully", Hash: common.HexToHash("0x123"), - ExpectedResult: types.NewReceipt([]byte{}, false, 0), + ExpectedResult: ethTypes.NewReceipt([]byte{}, false, 0), ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2477,7 +2978,7 @@ func TestGetTransactionReceipt(t *testing.T) { Return(m.DbTx, nil). Once() - tx := types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix("0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "0x")) require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) @@ -2502,7 +3003,7 @@ func TestGetTransactionReceipt(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2523,8 +3024,8 @@ func TestGetTransactionReceipt(t *testing.T) { Name: "Get TX receipt but failed to get tx", Hash: common.HexToHash("0x123"), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get tx from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get tx from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2546,7 +3047,7 @@ func TestGetTransactionReceipt(t *testing.T) { Hash: common.HexToHash("0x123"), ExpectedResult: nil, ExpectedError: ethereum.NotFound, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Commit", context.Background()). Return(nil). @@ -2557,7 +3058,7 @@ func TestGetTransactionReceipt(t *testing.T) { Return(m.DbTx, nil). Once() - tx := types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix("0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "0x")) require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) @@ -2581,8 +3082,8 @@ func TestGetTransactionReceipt(t *testing.T) { Name: "TX receipt failed to load", Hash: common.HexToHash("0x123"), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get tx receipt from state"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get tx receipt from state"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2593,7 +3094,7 @@ func TestGetTransactionReceipt(t *testing.T) { Return(m.DbTx, nil). Once() - tx := types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix("0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "0x")) require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) @@ -2617,8 +3118,8 @@ func TestGetTransactionReceipt(t *testing.T) { Name: "Get TX but failed to build response Successfully", Hash: common.HexToHash("0x123"), ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to build the receipt response"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to build the receipt response"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -2629,7 +3130,7 @@ func TestGetTransactionReceipt(t *testing.T) { Return(m.DbTx, nil). Once() - tx := types.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{}) m.State. On("GetTransactionByHash", context.Background(), tc.Hash, m.DbTx). @@ -2638,7 +3139,7 @@ func TestGetTransactionReceipt(t *testing.T) { m.State. On("GetTransactionReceipt", context.Background(), tc.Hash, m.DbTx). - Return(types.NewReceipt([]byte{}, false, 0), nil). + Return(ethTypes.NewReceipt([]byte{}, false, 0), nil). Once() }, }, @@ -2656,8 +3157,8 @@ func TestGetTransactionReceipt(t *testing.T) { } if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2674,42 +3175,42 @@ func TestSendRawTransactionViaGeth(t *testing.T) { type testCase struct { Name string - Tx *types.Transaction + Tx *ethTypes.Transaction ExpectedError interface{} - SetupMocks func(t *testing.T, m *mocks, tc testCase) + SetupMocks func(t *testing.T, m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Send TX successfully", - Tx: types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), + Tx: ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), ExpectedError: nil, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - txMatchByHash := mock.MatchedBy(func(tx types.Transaction) bool { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + txMatchByHash := mock.MatchedBy(func(tx ethTypes.Transaction) bool { h1 := tx.Hash().Hex() h2 := tc.Tx.Hash().Hex() return h1 == h2 }) m.Pool. - On("AddTx", context.Background(), txMatchByHash). + On("AddTx", context.Background(), txMatchByHash, ""). Return(nil). Once() }, }, { Name: "Send TX failed to add to the pool", - Tx: types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), - ExpectedError: newRPCError(defaultErrorCode, "failed to add TX to the pool"), - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - txMatchByHash := mock.MatchedBy(func(tx types.Transaction) bool { + Tx: ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to add TX to the pool"), + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + txMatchByHash := mock.MatchedBy(func(tx ethTypes.Transaction) bool { h1 := tx.Hash().Hex() h2 := tc.Tx.Hash().Hex() return h1 == h2 }) m.Pool. - On("AddTx", context.Background(), txMatchByHash). + On("AddTx", context.Background(), txMatchByHash, ""). Return(errors.New("failed to add TX to the pool")). Once() }, @@ -2724,8 +3225,8 @@ func TestSendRawTransactionViaGeth(t *testing.T) { err := c.SendTransaction(context.Background(), tc.Tx) if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2744,16 +3245,16 @@ func TestSendRawTransactionJSONRPCCall(t *testing.T) { Name string Input string ExpectedResult *common.Hash - ExpectedError rpcError + ExpectedError types.Error Prepare func(t *testing.T, tc *testCase) - SetupMocks func(t *testing.T, m *mocks, tc testCase) + SetupMocks func(t *testing.T, m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Send TX successfully", Prepare: func(t *testing.T, tc *testCase) { - tx := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}) txBinary, err := tx.MarshalBinary() require.NoError(t, err) @@ -2762,12 +3263,12 @@ func TestSendRawTransactionJSONRPCCall(t *testing.T) { require.NoError(t, err) tc.Input = rawTx - tc.ExpectedResult = hashPtr(tx.Hash()) + tc.ExpectedResult = state.HashPtr(tx.Hash()) tc.ExpectedError = nil }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Pool. - On("AddTx", context.Background(), mock.IsType(types.Transaction{})). + On("AddTx", context.Background(), mock.IsType(ethTypes.Transaction{}), ""). Return(nil). Once() }, @@ -2775,7 +3276,7 @@ func TestSendRawTransactionJSONRPCCall(t *testing.T) { { Name: "Send TX failed to add to the pool", Prepare: func(t *testing.T, tc *testCase) { - tx := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}) + tx := ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}) txBinary, err := tx.MarshalBinary() require.NoError(t, err) @@ -2785,11 +3286,11 @@ func TestSendRawTransactionJSONRPCCall(t *testing.T) { tc.Input = rawTx tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to add TX to the pool") + tc.ExpectedError = types.NewRPCError(types.DefaultErrorCode, "failed to add TX to the pool") }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Pool. - On("AddTx", context.Background(), mock.IsType(types.Transaction{})). + On("AddTx", context.Background(), mock.IsType(ethTypes.Transaction{}), ""). Return(errors.New("failed to add TX to the pool")). Once() }, @@ -2799,9 +3300,9 @@ func TestSendRawTransactionJSONRPCCall(t *testing.T) { Prepare: func(t *testing.T, tc *testCase) { tc.Input = "0x1234" tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(invalidParamsErrorCode, "invalid tx input") + tc.ExpectedError = types.NewRPCError(types.InvalidParamsErrorCode, "invalid tx input") }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) {}, + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) {}, }, } @@ -2839,42 +3340,42 @@ func TestSendRawTransactionViaGethForNonSequencerNode(t *testing.T) { type testCase struct { Name string - Tx *types.Transaction + Tx *ethTypes.Transaction ExpectedError interface{} - SetupMocks func(t *testing.T, m *mocks, tc testCase) + SetupMocks func(t *testing.T, m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Send TX successfully", - Tx: types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), + Tx: ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), ExpectedError: nil, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - txMatchByHash := mock.MatchedBy(func(tx types.Transaction) bool { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + txMatchByHash := mock.MatchedBy(func(tx ethTypes.Transaction) bool { h1 := tx.Hash().Hex() h2 := tc.Tx.Hash().Hex() return h1 == h2 }) m.Pool. - On("AddTx", context.Background(), txMatchByHash). + On("AddTx", context.Background(), txMatchByHash, ""). Return(nil). Once() }, }, { Name: "Send TX failed to add to the pool", - Tx: types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), - ExpectedError: newRPCError(defaultErrorCode, "failed to add TX to the pool"), - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - txMatchByHash := mock.MatchedBy(func(tx types.Transaction) bool { + Tx: ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to add TX to the pool"), + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + txMatchByHash := mock.MatchedBy(func(tx ethTypes.Transaction) bool { h1 := tx.Hash().Hex() h2 := tc.Tx.Hash().Hex() return h1 == h2 }) m.Pool. - On("AddTx", context.Background(), txMatchByHash). + On("AddTx", context.Background(), txMatchByHash, ""). Return(errors.New("failed to add TX to the pool")). Once() }, @@ -2889,8 +3390,8 @@ func TestSendRawTransactionViaGethForNonSequencerNode(t *testing.T) { err := nonSequencerClient.SendTransaction(context.Background(), tc.Tx) if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2907,15 +3408,15 @@ func TestSendRawTransactionViaGethForNonSequencerNodeFailsToRelayTxToSequencerNo type testCase struct { Name string - Tx *types.Transaction + Tx *ethTypes.Transaction ExpectedError interface{} } testCases := []testCase{ { Name: "Send TX failed to relay tx to the sequencer node", - Tx: types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), - ExpectedError: newRPCError(defaultErrorCode, "failed to relay tx to the sequencer node"), + Tx: ethTypes.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), uint64(1), big.NewInt(1), []byte{}), + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to relay tx to the sequencer node"), }, } @@ -2926,8 +3427,8 @@ func TestSendRawTransactionViaGethForNonSequencerNodeFailsToRelayTxToSequencerNo err := nonSequencerClient.SendTransaction(context.Background(), tc.Tx) if err != nil || testCase.ExpectedError != nil { - if expectedErr, ok := testCase.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := testCase.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -2962,34 +3463,56 @@ func TestNewFilter(t *testing.T) { type testCase struct { Name string - LogFilter *LogFilter - ExpectedResult argUint64 - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + Request types.LogFilterRequest + ExpectedResult string + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } + hash := common.HexToHash("0x42") + blockNumber := "8" testCases := []testCase{ { - Name: "New filter created successfully", - LogFilter: &LogFilter{}, - ExpectedResult: argUint64(1), + Name: "New filter created successfully", + Request: types.LogFilterRequest{ + ToBlock: &blockNumber, + }, + ExpectedResult: "1", ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("NewLogFilter", *tc.LogFilter). - Return(uint64(1), nil). + On("NewLogFilter", mock.IsType(&websocket.Conn{}), mock.IsType(LogFilter{})). + Return("1", nil). + Once() + }, + }, + { + Name: "failed to create new filter", + Request: types.LogFilterRequest{ + BlockHash: &hash, + }, + ExpectedResult: "", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to create new log filter"), + SetupMocks: func(m *mocksWrapper, tc testCase) { + m.Storage. + On("NewLogFilter", mock.IsType(&websocket.Conn{}), mock.IsType(LogFilter{})). + Return("", errors.New("failed to add new filter")). Once() }, }, { - Name: "failed to create new filter", - LogFilter: &LogFilter{}, - ExpectedResult: argUint64(0), - ExpectedError: newRPCError(defaultErrorCode, "failed to create new log filter"), - SetupMocks: func(m *mocks, tc testCase) { + Name: "failed to create new filter because BlockHash and ToBlock are present", + Request: types.LogFilterRequest{ + BlockHash: &hash, + ToBlock: &blockNumber, + }, + ExpectedResult: "", + ExpectedError: types.NewRPCError(types.InvalidParamsErrorCode, "invalid argument 0: cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("NewLogFilter", *tc.LogFilter). - Return(uint64(0), errors.New("failed to add new filter")). + On("NewLogFilter", mock.IsType(&websocket.Conn{}), mock.IsType(LogFilter{})). + Once(). + Return("", ErrFilterInvalidPayload). Once() }, }, @@ -3000,14 +3523,14 @@ func TestNewFilter(t *testing.T) { tc := testCase tc.SetupMocks(m, tc) - res, err := s.JSONRPCCall("eth_newFilter", tc.LogFilter) + res, err := s.JSONRPCCall("eth_newFilter", tc.Request) require.NoError(t, err) assert.Equal(t, float64(1), res.ID) assert.Equal(t, "2.0", res.JSONRPC) if res.Result != nil { - var result argUint64 + var result string err = json.Unmarshal(res.Result, &result) require.NoError(t, err) assert.Equal(t, tc.ExpectedResult, result) @@ -3027,31 +3550,31 @@ func TestNewBlockFilter(t *testing.T) { type testCase struct { Name string - ExpectedResult argUint64 - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedResult string + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "New block filter created successfully", - ExpectedResult: argUint64(1), + ExpectedResult: "1", ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("NewBlockFilter"). - Return(uint64(1), nil). + On("NewBlockFilter", mock.IsType(&websocket.Conn{})). + Return("1", nil). Once() }, }, { Name: "failed to create new block filter", - ExpectedResult: argUint64(0), - ExpectedError: newRPCError(defaultErrorCode, "failed to create new block filter"), - SetupMocks: func(m *mocks, tc testCase) { + ExpectedResult: "", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to create new block filter"), + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("NewBlockFilter"). - Return(uint64(0), errors.New("failed to add new block filter")). + On("NewBlockFilter", mock.IsType(&websocket.Conn{})). + Return("", errors.New("failed to add new block filter")). Once() }, }, @@ -3069,7 +3592,7 @@ func TestNewBlockFilter(t *testing.T) { assert.Equal(t, "2.0", res.JSONRPC) if res.Result != nil { - var result argUint64 + var result string err = json.Unmarshal(res.Result, &result) require.NoError(t, err) assert.Equal(t, tc.ExpectedResult, result) @@ -3089,33 +3612,39 @@ func TestNewPendingTransactionFilter(t *testing.T) { type testCase struct { Name string - ExpectedResult argUint64 - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedResult string + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ + // { + // Name: "New pending transaction filter created successfully", + // ExpectedResult: "1", + // ExpectedError: nil, + // SetupMocks: func(m *mocks, tc testCase) { + // m.Storage. + // On("NewPendingTransactionFilter", mock.IsType(&websocket.Conn{})). + // Return("1", nil). + // Once() + // }, + // }, + // { + // Name: "failed to create new pending transaction filter", + // ExpectedResult: "", + // ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to create new pending transaction filter"), + // SetupMocks: func(m *mocks, tc testCase) { + // m.Storage. + // On("NewPendingTransactionFilter", mock.IsType(&websocket.Conn{})). + // Return("", errors.New("failed to add new pending transaction filter")). + // Once() + // }, + // }, { - Name: "New pending transaction filter created successfully", - ExpectedResult: argUint64(1), - ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { - m.Storage. - On("NewPendingTransactionFilter"). - Return(uint64(1), nil). - Once() - }, - }, - { - Name: "failed to create new pending transaction filter", - ExpectedResult: argUint64(0), - ExpectedError: newRPCError(defaultErrorCode, "failed to create new pending transaction filter"), - SetupMocks: func(m *mocks, tc testCase) { - m.Storage. - On("NewPendingTransactionFilter"). - Return(uint64(0), errors.New("failed to add new pending transaction filter")). - Once() - }, + Name: "can't create pending tx filter", + ExpectedResult: "", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "not supported yet"), + SetupMocks: func(m *mocksWrapper, tc testCase) {}, }, } @@ -3131,7 +3660,7 @@ func TestNewPendingTransactionFilter(t *testing.T) { assert.Equal(t, "2.0", res.JSONRPC) if res.Result != nil { - var result argUint64 + var result string err = json.Unmarshal(res.Result, &result) require.NoError(t, err) assert.Equal(t, tc.ExpectedResult, result) @@ -3151,46 +3680,34 @@ func TestUninstallFilter(t *testing.T) { type testCase struct { Name string - FilterID argUint64 + FilterID string ExpectedResult bool - ExpectedError rpcError - SetupMocks func(m *mocks, tc testCase) + ExpectedError types.Error + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Uninstalls filter successfully", - FilterID: argUint64(1), + FilterID: "1", ExpectedResult: true, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("UninstallFilter", uint64(tc.FilterID)). - Return(true, nil). + On("UninstallFilter", tc.FilterID). + Return(nil). Once() }, }, { Name: "filter already uninstalled", - FilterID: argUint64(1), + FilterID: "1", ExpectedResult: false, ExpectedError: nil, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.Storage. - On("UninstallFilter", uint64(tc.FilterID)). - Return(false, nil). - Once() - }, - }, - { - Name: "failed to uninstall filter", - FilterID: argUint64(1), - ExpectedResult: false, - ExpectedError: newRPCError(defaultErrorCode, "failed to uninstall filter"), - SetupMocks: func(m *mocks, tc testCase) { - m.Storage. - On("UninstallFilter", uint64(tc.FilterID)). - Return(false, errors.New("failed to uninstall filter")). + On("UninstallFilter", tc.FilterID). + Return(ErrNotFound). Once() }, }, @@ -3229,10 +3746,10 @@ func TestGetLogs(t *testing.T) { type testCase struct { Name string Filter ethereum.FilterQuery - ExpectedResult []types.Log + ExpectedResult []ethTypes.Log ExpectedError interface{} Prepare func(t *testing.T, tc *testCase) - SetupMocks func(m *mocks, tc testCase) + SetupMocks func(m *mocksWrapper, tc testCase) } testCases := []testCase{ @@ -3244,16 +3761,16 @@ func TestGetLogs(t *testing.T) { Addresses: []common.Address{common.HexToAddress("0x111")}, Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } - tc.ExpectedResult = []types.Log{{ + tc.ExpectedResult = []ethTypes.Log{{ Address: common.Address{}, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: uint64(1), TxHash: common.Hash{}, TxIndex: uint(1), BlockHash: common.Hash{}, Index: uint(1), Removed: false, }} tc.ExpectedError = nil }, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { var since *time.Time - logs := make([]*types.Log, 0, len(tc.ExpectedResult)) + logs := make([]*ethTypes.Log, 0, len(tc.ExpectedResult)) for _, log := range tc.ExpectedResult { l := log logs = append(logs, &l) @@ -3284,9 +3801,9 @@ func TestGetLogs(t *testing.T) { Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to get logs from state") + tc.ExpectedError = types.NewRPCError(types.DefaultErrorCode, "failed to get logs from state") }, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { var since *time.Time m.DbTx. On("Rollback", context.Background()). @@ -3313,9 +3830,9 @@ func TestGetLogs(t *testing.T) { Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to get the last block number from state") + tc.ExpectedError = types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state") }, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -3341,9 +3858,9 @@ func TestGetLogs(t *testing.T) { Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to get the last block number from state") + tc.ExpectedError = types.NewRPCError(types.DefaultErrorCode, "failed to get the last block number from state") }, - SetupMocks: func(m *mocks, tc testCase) { + SetupMocks: func(m *mocksWrapper, tc testCase) { m.DbTx. On("Rollback", context.Background()). Return(nil). @@ -3375,8 +3892,8 @@ func TestGetLogs(t *testing.T) { } if err != nil || tc.ExpectedError != nil { - if expectedErr, ok := tc.ExpectedError.(*RPCError); ok { - rpcErr := err.(rpcError) + if expectedErr, ok := tc.ExpectedError.(*types.RPCError); ok { + rpcErr := err.(rpc.Error) assert.Equal(t, expectedErr.ErrorCode(), rpcErr.ErrorCode()) assert.Equal(t, expectedErr.Error(), rpcErr.Error()) } else { @@ -3393,50 +3910,49 @@ func TestGetFilterLogs(t *testing.T) { type testCase struct { Name string - FilterID argUint64 - ExpectedResult []types.Log - ExpectedError rpcError + FilterID string + ExpectedResult []ethTypes.Log + ExpectedError types.Error Prepare func(t *testing.T, tc *testCase) - SetupMocks func(t *testing.T, m *mocks, tc testCase) + SetupMocks func(t *testing.T, m *mocksWrapper, tc testCase) } testCases := []testCase{ { Name: "Get filter logs successfully", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) - tc.ExpectedResult = []types.Log{{ + tc.FilterID = "1" + tc.ExpectedResult = []ethTypes.Log{{ Address: common.Address{}, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: uint64(1), TxHash: common.Hash{}, TxIndex: uint(1), BlockHash: common.Hash{}, Index: uint(1), Removed: false, }} tc.ExpectedError = nil }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { var since *time.Time - logs := make([]*types.Log, 0, len(tc.ExpectedResult)) + logs := make([]*ethTypes.Log, 0, len(tc.ExpectedResult)) for _, log := range tc.ExpectedResult { l := log logs = append(logs, &l) } + bn1 := types.BlockNumber(1) + bn2 := types.BlockNumber(2) logFilter := LogFilter{ - FromBlock: BlockNumber(1), ToBlock: BlockNumber(2), + FromBlock: &bn1, + ToBlock: &bn2, Addresses: []common.Address{common.HexToAddress("0x111")}, Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } - logFilterJSON, err := json.Marshal(&logFilter) - require.NoError(t, err) - - parameters := string(logFilterJSON) - filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeLog, LastPoll: time.Now(), - Parameters: parameters, + Parameters: logFilter, } + m.DbTx. On("Commit", context.Background()). Return(nil). @@ -3448,12 +3964,12 @@ func TestGetFilterLogs(t *testing.T) { Once() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, since, m.DbTx). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, since, m.DbTx). Return(logs, nil). Once() }, @@ -3461,13 +3977,13 @@ func TestGetFilterLogs(t *testing.T) { { Name: "Get filter logs filter not found", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" tc.ExpectedResult = nil tc.ExpectedError = nil }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(nil, ErrNotFound). Once() }, @@ -3475,13 +3991,13 @@ func TestGetFilterLogs(t *testing.T) { { Name: "Get filter logs failed to get filter", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to get filter from storage") + tc.ExpectedError = types.NewRPCError(types.DefaultErrorCode, "failed to get filter from storage") }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(nil, errors.New("failed to get filter")). Once() }, @@ -3489,41 +4005,20 @@ func TestGetFilterLogs(t *testing.T) { { Name: "Get filter logs is a valid filter but its not a log filter", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" tc.ExpectedResult = nil tc.ExpectedError = nil }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeBlock, LastPoll: time.Now(), Parameters: "", } m.Storage. - On("GetFilter", uint64(tc.FilterID)). - Return(filter, nil). - Once() - }, - }, - { - Name: "Get filter logs failed to parse filter parameters", - Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) - tc.ExpectedResult = nil - tc.ExpectedError = newRPCError(defaultErrorCode, "failed to read filter parameters") - }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - filter := &Filter{ - ID: uint64(tc.FilterID), - Type: FilterTypeLog, - LastPoll: time.Now(), - Parameters: "invalid parameters", - } - - m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() }, @@ -3536,7 +4031,7 @@ func TestGetFilterLogs(t *testing.T) { tc.Prepare(t, &tc) tc.SetupMocks(t, m, tc) - res, err := s.JSONRPCCall("eth_getFilterLogs", hex.EncodeUint64(uint64(tc.FilterID))) + res, err := s.JSONRPCCall("eth_getFilterLogs", tc.FilterID) require.NoError(t, err) assert.Equal(t, float64(1), res.ID) assert.Equal(t, "2.0", res.JSONRPC) @@ -3547,7 +4042,7 @@ func TestGetFilterLogs(t *testing.T) { require.NoError(t, err) if result != nil || tc.ExpectedResult != nil { - var logs []types.Log + var logs []ethTypes.Log err = json.Unmarshal(res.Result, &logs) require.NoError(t, err) assert.ElementsMatch(t, tc.ExpectedResult, logs) @@ -3568,18 +4063,19 @@ func TestGetFilterChanges(t *testing.T) { type testCase struct { Name string - FilterID argUint64 + FilterID string ExpectedResults []interface{} - ExpectedErrors []rpcError + ExpectedErrors []types.Error Prepare func(t *testing.T, tc *testCase) - SetupMocks func(t *testing.T, m *mocks, tc testCase) + SetupMocks func(t *testing.T, m *mocksWrapper, tc testCase) } + var nilTx pgx.Tx testCases := []testCase{ { Name: "Get block filter changes multiple times successfully", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(2) + tc.FilterID = "2" // first call tc.ExpectedResults = append(tc.ExpectedResults, []common.Hash{ common.HexToHash("0x111"), @@ -3597,86 +4093,56 @@ func TestGetFilterChanges(t *testing.T) { tc.ExpectedResults = append(tc.ExpectedResults, []common.Hash{}) tc.ExpectedErrors = append(tc.ExpectedErrors, nil) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeBlock, LastPoll: time.Now(), Parameters: "{}", } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - m.State. - On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, m.DbTx). + On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, mock.IsType(nilTx)). Return(tc.ExpectedResults[0].([]common.Hash), nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - m.State. - On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, m.DbTx). + On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, mock.IsType(nilTx)). Return(tc.ExpectedResults[1].([]common.Hash), nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, m.DbTx). + On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, mock.IsType(nilTx)). Return(tc.ExpectedResults[2].([]common.Hash), nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(nil). Once() }). @@ -3690,7 +4156,7 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get pending transactions filter changes multiple times successfully", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(3) + tc.FilterID = "3" // first call tc.ExpectedResults = append(tc.ExpectedResults, []common.Hash{ common.HexToHash("0x444"), @@ -3708,16 +4174,16 @@ func TestGetFilterChanges(t *testing.T) { tc.ExpectedResults = append(tc.ExpectedResults, []common.Hash{}) tc.ExpectedErrors = append(tc.ExpectedErrors, nil) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypePendingTx, LastPoll: time.Now(), Parameters: "{}", } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() @@ -3727,12 +4193,12 @@ func TestGetFilterChanges(t *testing.T) { Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() @@ -3742,12 +4208,12 @@ func TestGetFilterChanges(t *testing.T) { Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() @@ -3757,7 +4223,7 @@ func TestGetFilterChanges(t *testing.T) { Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(nil). Once() }). @@ -3771,9 +4237,9 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get log filter changes multiple times successfully", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" // first call - tc.ExpectedResults = append(tc.ExpectedResults, []types.Log{{ + tc.ExpectedResults = append(tc.ExpectedResults, []ethTypes.Log{{ Address: common.Address{}, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: uint64(1), TxHash: common.Hash{}, TxIndex: uint(1), BlockHash: common.Hash{}, Index: uint(1), Removed: false, @@ -3781,7 +4247,7 @@ func TestGetFilterChanges(t *testing.T) { tc.ExpectedErrors = append(tc.ExpectedErrors, nil) // second call - tc.ExpectedResults = append(tc.ExpectedResults, []types.Log{{ + tc.ExpectedResults = append(tc.ExpectedResults, []ethTypes.Log{{ Address: common.Address{}, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: uint64(1), TxHash: common.Hash{}, TxIndex: uint(1), BlockHash: common.Hash{}, Index: uint(1), Removed: false, @@ -3796,109 +4262,78 @@ func TestGetFilterChanges(t *testing.T) { tc.ExpectedResults = append(tc.ExpectedResults, nil) tc.ExpectedErrors = append(tc.ExpectedErrors, nil) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + bn1 := types.BlockNumber(1) + bn2 := types.BlockNumber(2) logFilter := LogFilter{ - FromBlock: BlockNumber(1), ToBlock: BlockNumber(2), + FromBlock: &bn1, ToBlock: &bn2, Addresses: []common.Address{common.HexToAddress("0x111")}, Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } - logFilterJSON, err := json.Marshal(&logFilter) - require.NoError(t, err) - - parameters := string(logFilterJSON) - filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeLog, LastPoll: time.Now(), - Parameters: parameters, + Parameters: logFilter, } - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - expectedLogs := tc.ExpectedResults[0].([]types.Log) - logs := make([]*types.Log, 0, len(expectedLogs)) + expectedLogs := tc.ExpectedResults[0].([]ethTypes.Log) + logs := make([]*ethTypes.Log, 0, len(expectedLogs)) for _, log := range expectedLogs { l := log logs = append(logs, &l) } m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, m.DbTx). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, mock.IsType(nilTx)). Return(logs, nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - expectedLogs = tc.ExpectedResults[1].([]types.Log) - logs = make([]*types.Log, 0, len(expectedLogs)) + expectedLogs = tc.ExpectedResults[1].([]ethTypes.Log) + logs = make([]*ethTypes.Log, 0, len(expectedLogs)) for _, log := range expectedLogs { l := log logs = append(logs, &l) } m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, m.DbTx). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, mock.IsType(nilTx)). Return(logs, nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Run(func(args mock.Arguments) { filter.LastPoll = time.Now() - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, m.DbTx). - Return([]*types.Log{}, nil). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, mock.IsType(nilTx)). + Return([]*ethTypes.Log{}, nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(nil). Once() }). @@ -3912,14 +4347,14 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get filter changes when filter is not found", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" // first call tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, nil) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "filter not found")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(nil, ErrNotFound). Once() }, @@ -3927,81 +4362,40 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get filter changes fails to get filter", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" // first call tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to get filter from storage")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to get filter from storage")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(nil, errors.New("failed to get filter")). Once() }, }, - { - Name: "Get log filter changes fails to parse parameters", - Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) - // first call - tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to read filter parameters")) - }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { - filter := &Filter{ - ID: uint64(tc.FilterID), - Type: FilterTypeLog, - LastPoll: time.Now(), - Parameters: "invalid parameters", - } - - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.Storage. - On("GetFilter", uint64(tc.FilterID)). - Return(filter, nil). - Once() - }, - }, { Name: "Get block filter changes fails to get block hashes", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(2) + tc.FilterID = "2" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to get block hashes")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to get block hashes")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeBlock, LastPoll: time.Now(), - Parameters: "{}", + Parameters: LogFilter{}, } - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() m.State. - On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, m.DbTx). + On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, mock.IsType(nilTx)). Return([]common.Hash{}, errors.New("failed to get hashes")). Once() }, @@ -4009,40 +4403,30 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get block filter changes fails to update the last time it was requested", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(2) + tc.FilterID = "2" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to update last time the filter changes were requested")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to update last time the filter changes were requested")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeBlock, LastPoll: time.Now(), - Parameters: "{}", + Parameters: LogFilter{}, } - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() m.State. - On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, m.DbTx). + On("GetL2BlockHashesSince", context.Background(), filter.LastPoll, mock.IsType(nilTx)). Return([]common.Hash{}, nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(errors.New("failed to update filter last poll")). Once() }, @@ -4050,20 +4434,20 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get pending transactions filter fails to get the hashes", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(3) + tc.FilterID = "3" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to get pending transaction hashes")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to get pending transaction hashes")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypePendingTx, LastPoll: time.Now(), - Parameters: "{}", + Parameters: LogFilter{}, } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() @@ -4076,20 +4460,20 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get pending transactions fails to update the last time it was requested", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(3) + tc.FilterID = "3" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to update last time the filter changes were requested")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to update last time the filter changes were requested")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypePendingTx, LastPoll: time.Now(), - Parameters: "{}", + Parameters: LogFilter{}, } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() @@ -4099,7 +4483,7 @@ func TestGetFilterChanges(t *testing.T) { Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(errors.New("failed to update filter last poll")). Once() }, @@ -4107,45 +4491,34 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get log filter changes fails to get logs", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to get logs from state")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to get logs from state")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + bn1 := types.BlockNumber(1) + bn2 := types.BlockNumber(2) logFilter := LogFilter{ - FromBlock: BlockNumber(1), ToBlock: BlockNumber(2), + + FromBlock: &bn1, ToBlock: &bn2, Addresses: []common.Address{common.HexToAddress("0x111")}, Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } - logFilterJSON, err := json.Marshal(&logFilter) - require.NoError(t, err) - - parameters := string(logFilterJSON) - filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeLog, LastPoll: time.Now(), - Parameters: parameters, + Parameters: logFilter, } - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, m.DbTx). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, mock.IsType(nilTx)). Return(nil, errors.New("failed to get logs")). Once() }, @@ -4153,51 +4526,38 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get log filter changes fails to update the last time it was requested", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(1) + tc.FilterID = "1" tc.ExpectedResults = append(tc.ExpectedResults, nil) - tc.ExpectedErrors = append(tc.ExpectedErrors, newRPCError(defaultErrorCode, "failed to update last time the filter changes were requested")) + tc.ExpectedErrors = append(tc.ExpectedErrors, types.NewRPCError(types.DefaultErrorCode, "failed to update last time the filter changes were requested")) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { + bn1 := types.BlockNumber(1) + bn2 := types.BlockNumber(2) logFilter := LogFilter{ - FromBlock: BlockNumber(1), ToBlock: BlockNumber(2), + FromBlock: &bn1, ToBlock: &bn2, Addresses: []common.Address{common.HexToAddress("0x111")}, Topics: [][]common.Hash{{common.HexToHash("0x222")}}, } - logFilterJSON, err := json.Marshal(&logFilter) - require.NoError(t, err) - - parameters := string(logFilterJSON) - filter := &Filter{ - ID: uint64(tc.FilterID), + ID: tc.FilterID, Type: FilterTypeLog, LastPoll: time.Now(), - Parameters: parameters, + Parameters: logFilter, } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("GetLogs", context.Background(), uint64(logFilter.FromBlock), uint64(logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, m.DbTx). - Return([]*types.Log{}, nil). + On("GetLogs", context.Background(), uint64(*logFilter.FromBlock), uint64(*logFilter.ToBlock), logFilter.Addresses, logFilter.Topics, logFilter.BlockHash, &filter.LastPoll, mock.IsType(nilTx)). + Return([]*ethTypes.Log{}, nil). Once() m.Storage. - On("UpdateFilterLastPoll", uint64(tc.FilterID)). + On("UpdateFilterLastPoll", tc.FilterID). Return(errors.New("failed to update filter last poll")). Once() }, @@ -4205,17 +4565,17 @@ func TestGetFilterChanges(t *testing.T) { { Name: "Get filter changes for a unknown log type", Prepare: func(t *testing.T, tc *testCase) { - tc.FilterID = argUint64(4) + tc.FilterID = "4" tc.ExpectedResults = append(tc.ExpectedResults, nil) tc.ExpectedErrors = append(tc.ExpectedErrors, nil) }, - SetupMocks: func(t *testing.T, m *mocks, tc testCase) { + SetupMocks: func(t *testing.T, m *mocksWrapper, tc testCase) { filter := &Filter{ Type: "unknown type", } m.Storage. - On("GetFilter", uint64(tc.FilterID)). + On("GetFilter", tc.FilterID). Return(filter, nil). Once() }, @@ -4242,7 +4602,7 @@ func TestGetFilterChanges(t *testing.T) { require.NoError(t, err) if result != nil || tc.ExpectedResults[i] != nil { - if logs, ok := tc.ExpectedResults[i].([]types.Log); ok { + if logs, ok := tc.ExpectedResults[i].([]ethTypes.Log); ok { err = json.Unmarshal(res.Result, &logs) require.NoError(t, err) assert.ElementsMatch(t, tc.ExpectedResults[i], logs) @@ -4263,11 +4623,3 @@ func TestGetFilterChanges(t *testing.T) { }) } } - -func addressPtr(i common.Address) *common.Address { - return &i -} - -func hashPtr(h common.Hash) *common.Hash { - return &h -} diff --git a/jsonrpc/endpoints_net.go b/jsonrpc/endpoints_net.go new file mode 100644 index 0000000000..9b82c58f5b --- /dev/null +++ b/jsonrpc/endpoints_net.go @@ -0,0 +1,19 @@ +package jsonrpc + +import ( + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" +) + +// NetEndpoints contains implementations for the "net" RPC endpoints +type NetEndpoints struct { + cfg Config + chainID uint64 +} + +// Version returns the current network id +func (n *NetEndpoints) Version() (interface{}, types.Error) { + return strconv.FormatUint(n.chainID, encoding.Base10), nil +} diff --git a/jsonrpc/txpool.go b/jsonrpc/endpoints_txpool.go similarity index 67% rename from jsonrpc/txpool.go rename to jsonrpc/endpoints_txpool.go index a87875dd4f..edb68812d0 100644 --- a/jsonrpc/txpool.go +++ b/jsonrpc/endpoints_txpool.go @@ -1,11 +1,12 @@ package jsonrpc import ( + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/ethereum/go-ethereum/common" ) -// TxPool is the txpool jsonrpc endpoint -type TxPool struct{} +// TxPoolEndpoints is the txpool jsonrpc endpoint +type TxPoolEndpoints struct{} type contentResponse struct { Pending map[common.Address]map[uint64]*txPoolTransaction `json:"pending"` @@ -13,12 +14,12 @@ type contentResponse struct { } type txPoolTransaction struct { - Nonce argUint64 `json:"nonce"` - GasPrice argBig `json:"gasPrice"` - Gas argUint64 `json:"gas"` + Nonce types.ArgUint64 `json:"nonce"` + GasPrice types.ArgBig `json:"gasPrice"` + Gas types.ArgUint64 `json:"gas"` To *common.Address `json:"to"` - Value argBig `json:"value"` - Input argBytes `json:"input"` + Value types.ArgBig `json:"value"` + Input types.ArgBytes `json:"input"` Hash common.Hash `json:"hash"` From common.Address `json:"from"` BlockHash common.Hash `json:"blockHash"` @@ -28,7 +29,7 @@ type txPoolTransaction struct { // Content creates a response for txpool_content request. // See https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content. -func (t *TxPool) Content() (interface{}, rpcError) { +func (e *TxPoolEndpoints) Content() (interface{}, types.Error) { resp := contentResponse{ Pending: make(map[common.Address]map[uint64]*txPoolTransaction), Queued: make(map[common.Address]map[uint64]*txPoolTransaction), diff --git a/jsonrpc/endpoints_web3.go b/jsonrpc/endpoints_web3.go new file mode 100644 index 0000000000..da076bf1a7 --- /dev/null +++ b/jsonrpc/endpoints_web3.go @@ -0,0 +1,27 @@ +package jsonrpc + +import ( + "math/big" + + "github.com/0xPolygonHermez/zkevm-node" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "golang.org/x/crypto/sha3" +) + +// Web3Endpoints contains implementations for the "web3" RPC endpoints +type Web3Endpoints struct { +} + +// ClientVersion returns the client version. +func (e *Web3Endpoints) ClientVersion() (interface{}, types.Error) { + return zkevm.Version, nil +} + +// Sha3 returns the keccak256 hash of the given data. +func (e *Web3Endpoints) Sha3(data types.ArgBig) (interface{}, types.Error) { + b := (*big.Int)(&data) + hash := sha3.NewLegacyKeccak256() + hash.Write(b.Bytes()) //nolint:errcheck,gosec + keccak256Hash := hash.Sum(nil) + return types.ArgBytes(keccak256Hash), nil +} diff --git a/jsonrpc/web3_test.go b/jsonrpc/endpoints_web3_test.go similarity index 92% rename from jsonrpc/web3_test.go rename to jsonrpc/endpoints_web3_test.go index 9572167de4..4e2e5b2058 100644 --- a/jsonrpc/web3_test.go +++ b/jsonrpc/endpoints_web3_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "testing" + "github.com/0xPolygonHermez/zkevm-node" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -23,7 +24,7 @@ func TestClientVersion(t *testing.T) { err = json.Unmarshal(res.Result, &result) require.NoError(t, err) - assert.Equal(t, "Polygon Hermez zkEVM/v2.0.0", result) + assert.Equal(t, zkevm.Version, result) } func TestSha3(t *testing.T) { diff --git a/jsonrpc/endpoints_zkevm.go b/jsonrpc/endpoints_zkevm.go new file mode 100644 index 0000000000..1bd30f1baf --- /dev/null +++ b/jsonrpc/endpoints_zkevm.go @@ -0,0 +1,169 @@ +package jsonrpc + +import ( + "context" + "errors" + "fmt" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +// ZKEVMEndpoints contains implementations for the "zkevm" RPC endpoints +type ZKEVMEndpoints struct { + config Config + state types.StateInterface + txMan dbTxManager +} + +// ConsolidatedBlockNumber returns last block number related to the last verified batch +func (z *ZKEVMEndpoints) ConsolidatedBlockNumber() (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + lastBlockNumber, err := z.state.GetLastConsolidatedL2BlockNumber(ctx, dbTx) + if err != nil { + const errorMessage = "failed to get last consolidated block number from state" + log.Errorf("%v:%v", errorMessage, err) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + return hex.EncodeUint64(lastBlockNumber), nil + }) +} + +// IsBlockConsolidated returns the consolidation status of a provided block number +func (z *ZKEVMEndpoints) IsBlockConsolidated(blockNumber types.ArgUint64) (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + IsL2BlockConsolidated, err := z.state.IsL2BlockConsolidated(ctx, uint64(blockNumber), dbTx) + if err != nil { + const errorMessage = "failed to check if the block is consolidated" + log.Errorf("%v: %v", errorMessage, err) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + return IsL2BlockConsolidated, nil + }) +} + +// IsBlockVirtualized returns the virtualization status of a provided block number +func (z *ZKEVMEndpoints) IsBlockVirtualized(blockNumber types.ArgUint64) (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + IsL2BlockVirtualized, err := z.state.IsL2BlockVirtualized(ctx, uint64(blockNumber), dbTx) + if err != nil { + const errorMessage = "failed to check if the block is virtualized" + log.Errorf("%v: %v", errorMessage, err) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + return IsL2BlockVirtualized, nil + }) +} + +// BatchNumberByBlockNumber returns the batch number from which the passed block number is created +func (z *ZKEVMEndpoints) BatchNumberByBlockNumber(blockNumber types.ArgUint64) (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + batchNum, err := z.state.BatchNumberByL2BlockNumber(ctx, uint64(blockNumber), dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + const errorMessage = "failed to get batch number from block number" + log.Errorf("%v: %v", errorMessage, err.Error()) + return nil, types.NewRPCError(types.DefaultErrorCode, errorMessage) + } + + return hex.EncodeUint64(batchNum), nil + }) +} + +// BatchNumber returns the latest virtualized batch number +func (z *ZKEVMEndpoints) BatchNumber() (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + lastBatchNumber, err := z.state.GetLastBatchNumber(ctx, dbTx) + if err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get the last batch number from state") + } + + return hex.EncodeUint64(lastBatchNumber), nil + }) +} + +// VirtualBatchNumber returns the latest virtualized batch number +func (z *ZKEVMEndpoints) VirtualBatchNumber() (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + lastBatchNumber, err := z.state.GetLastVirtualBatchNum(ctx, dbTx) + if err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get the last virtual batch number from state") + } + + return hex.EncodeUint64(lastBatchNumber), nil + }) +} + +// VerifiedBatchNumber returns the latest verified batch number +func (z *ZKEVMEndpoints) VerifiedBatchNumber() (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + lastBatch, err := z.state.GetLastVerifiedBatch(ctx, dbTx) + if err != nil { + return "0x0", types.NewRPCError(types.DefaultErrorCode, "failed to get the last verified batch number from state") + } + + return hex.EncodeUint64(lastBatch.BatchNumber), nil + }) +} + +// GetBatchByNumber returns information about a batch by batch number +func (z *ZKEVMEndpoints) GetBatchByNumber(batchNumber types.BatchNumber, fullTx bool) (interface{}, types.Error) { + return z.txMan.NewDbTxScope(z.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) { + var err error + batchNumber, rpcErr := batchNumber.GetNumericBatchNumber(ctx, z.state, dbTx) + if rpcErr != nil { + return nil, rpcErr + } + + batch, err := z.state.GetBatchByNumber(ctx, batchNumber, dbTx) + if errors.Is(err, state.ErrNotFound) { + return nil, nil + } else if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load batch from state by number %v", batchNumber), err) + } + + txs, err := z.state.GetTransactionsByBatchNumber(ctx, batchNumber, dbTx) + if !errors.Is(err, state.ErrNotFound) && err != nil { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load batch txs from state by number %v", batchNumber), err) + } + + receipts := make([]ethTypes.Receipt, 0, len(txs)) + for _, tx := range txs { + receipt, err := z.state.GetTransactionReceipt(ctx, tx.Hash(), dbTx) + if err != nil { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load receipt for tx %v", tx.Hash().String()), err) + } + receipts = append(receipts, *receipt) + } + + virtualBatch, err := z.state.GetVirtualBatch(ctx, batchNumber, dbTx) + if err != nil && !errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load virtual batch from state by number %v", batchNumber), err) + } + + verifiedBatch, err := z.state.GetVerifiedBatch(ctx, batchNumber, dbTx) + if err != nil && !errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load virtual batch from state by number %v", batchNumber), err) + } + + ger, err := z.state.GetExitRootByGlobalExitRoot(ctx, batch.GlobalExitRoot, dbTx) + if err != nil && !errors.Is(err, state.ErrNotFound) { + return rpcErrorResponse(types.DefaultErrorCode, fmt.Sprintf("couldn't load full GER from state by number %v", batchNumber), err) + } else if errors.Is(err, state.ErrNotFound) { + ger = &state.GlobalExitRoot{} + } + + batch.Transactions = txs + rpcBatch := types.NewBatch(batch, virtualBatch, verifiedBatch, receipts, fullTx, ger) + + return rpcBatch, nil + }) +} diff --git a/jsonrpc/endpoints_zkevm.openrpc.json b/jsonrpc/endpoints_zkevm.openrpc.json new file mode 100644 index 0000000000..0f205fc39c --- /dev/null +++ b/jsonrpc/endpoints_zkevm.openrpc.json @@ -0,0 +1,566 @@ +{ + "openrpc": "1.0.0-rc1", + "info": { + "title": "zkEVM Endpoints", + "version": "2.0.0" + }, + "methods": [ + { + "name": "zkevm_consolidatedBlockNumber", + "summary": "Returns the latest block number that is connected to the latest batch verified.", + "params": [], + "result": { + "$ref": "#/components/contentDescriptors/BlockNumber" + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": "0x1" + } + } + ] + }, + { + "name": "zkevm_isBlockVirtualized", + "summary": "Returns true if the provided block number is already connected to a batch that was already virtualized, otherwise false.", + "params": [ + { + "name": "blockNumber", + "schema": { + "$ref": "#/components/contentDescriptors/BlockNumber" + } + } + ], + "result": { + "name": "result", + "schema": { + "type": "boolean" + } + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": true + } + } + ] + }, + { + "name": "zkevm_isBlockConsolidated", + "summary": "Returns true if the provided block number is already connected to a batch that was already verified, otherwise false.", + "params": [ + { + "$ref": "#/components/contentDescriptors/BlockNumber" + } + ], + "result": { + "name": "result", + "schema": { + "type": "boolean" + } + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": true + } + } + ] + }, + { + "name": "zkevm_batchNumber", + "summary": "Returns the latest batch number.", + "params": [], + "result": { + "$ref": "#/components/contentDescriptors/BatchNumber" + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": "0x1" + } + } + ] + }, + { + "name": "zkevm_virtualBatchNumber", + "summary": "Returns the latest virtual batch number.", + "params": [], + "result": { + "$ref": "#/components/contentDescriptors/BatchNumber" + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": "0x1" + } + } + ] + }, + { + "name": "zkevm_verifiedBatchNumber", + "summary": "Returns the latest verified batch number.", + "params": [], + "result": { + "$ref": "#/components/contentDescriptors/BatchNumber" + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": "0x1" + } + } + ] + }, + { + "name": "zkevm_batchNumberByBlockNumber", + "summary": "Returns the batch number of the batch connected to the block.", + "params": [ + { + "$ref": "#/components/contentDescriptors/BlockNumber" + } + ], + "result": { + "$ref": "#/components/contentDescriptors/BatchNumber" + }, + "examples": [ + { + "name": "example", + "description": "", + "params": [], + "result": { + "name": "exampleResult", + "description": "", + "value": "0x1" + } + } + ] + }, + { + "name": "zkevm_getBatchByNumber", + "summary": "Gets a batch for a given number", + "params": [ + { + "$ref": "#/components/contentDescriptors/BatchNumberOrTag" + }, + { + "name": "includeTransactions", + "description": "If `true` it returns the full transaction objects, if `false` only the hashes of the transactions.", + "required": true, + "schema": { + "title": "isTransactionsIncluded", + "type": "boolean" + } + } + ], + "result": { + "$ref": "#/components/contentDescriptors/Batch" + }, + "examples": [ + { + "name": "batch without tx details", + "description": "Batch without transaction details", + "params": [ + { + "name": "batch number", + "value": "0x1" + }, + { + "name": "include txs", + "value": "false" + } + ], + "result": { + "name": "Batch", + "value": { + "number": "0x1", + "coinbase": "0x0000000000000000000000000000000000000001", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000001", + "globalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000002", + "mainnetExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", + "rollupExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000004", + "localExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000005", + "accInputHash": "0x0000000000000000000000000000000000000000000000000000000000000006", + "timestamp": "0x642af31f", + "sendSequencesTxHash": "0x0000000000000000000000000000000000000000000000000000000000000007", + "verifyBatchTxHash": "0x0000000000000000000000000000000000000000000000000000000000000008", + "transactions": [ + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000011" + ] + } + } + }, + { + "name": "batch with tx detail", + "description": "Batch with transaction details", + "params": [ + { + "name": "batch number", + "value": "0x1" + }, + { + "name": "include txs", + "value": "true" + } + ], + "result": { + "name": "Batch", + "value": { + "number": "0x1", + "coinbase": "0x0000000000000000000000000000000000000001", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000001", + "globalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000002", + "mainnetExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", + "rollupExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000004", + "localExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000005", + "accInputHash": "0x0000000000000000000000000000000000000000000000000000000000000006", + "timestamp": "0x642af31f", + "sendSequencesTxHash": "0x0000000000000000000000000000000000000000000000000000000000000007", + "verifyBatchTxHash": "0x0000000000000000000000000000000000000000000000000000000000000008", + "transactions": [ + { + "nonce": "0x1", + "gasPrice": "0x123456", + "gas": "0x59D8", + "to": "0x0000000000000000000000000000000000000002", + "value": "0x1", + "input": "0x", + "v": "0xAAA", + "r": "0x0000000000000000000000000000000000000000000000000000000000000010", + "s": "0x0000000000000000000000000000000000000000000000000000000000000011", + "hash": "0x0000000000000000000000000000000000000000000000000000000000000012", + "from": "0x0000000000000000000000000000000000000003", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000013", + "blockNumber": "0x1", + "transactionIndex": "0x0", + "chainId": "0x539", + "type": "0x0" + } + ] + } + } + } + ] + } + ], + "components": { + "contentDescriptors": { + "BlockNumber": { + "name": "blockNumber", + "required": true, + "schema": { + "$ref": "#/components/schemas/BlockNumber" + } + }, + "BatchNumber": { + "name": "batchNumber", + "required": true, + "schema": { + "$ref": "#/components/schemas/BatchNumber" + } + }, + "BatchNumberOrTag": { + "name": "batchNumberOrTag", + "required": true, + "schema": { + "title": "batchNumberOrTag", + "oneOf": [ + { + "$ref": "#/components/schemas/BatchNumber" + }, + { + "$ref": "#/components/schemas/BatchNumberTag" + } + ] + } + }, + "Batch": { + "name": "batch", + "description": "batch", + "required": true, + "schema": { + "$ref": "#/components/schemas/Batch" + } + } + }, + "schemas": { + "Null": { + "title": "null", + "type": "null", + "description": "Null" + }, + "BatchNumberTag": { + "title": "batchNumberTag", + "type": "string", + "description": "The optional batch height description", + "enum": [ + "earliest", + "latest" + ] + }, + "Integer": { + "title": "integer", + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$", + "description": "Hex representation of the integer" + }, + "Keccak": { + "title": "keccak", + "type": "string", + "description": "Hex representation of a Keccak 256 hash", + "pattern": "^0x[a-fA-F\\d]{64}$" + }, + "Address": { + "title": "address", + "type": "string", + "pattern": "^0x[a-fA-F\\d]{40}$" + }, + "BlockNumber": { + "title": "blockNumber", + "type": "string", + "description": "The hex representation of the block's height", + "$ref": "#/components/schemas/Integer" + }, + "BatchNumber": { + "title": "batchNumber", + "type": "string", + "description": "The hex representation of the batch's height", + "$ref": "#/components/schemas/Integer" + }, + "TransactionHash": { + "title": "transactionHash", + "type": "string", + "description": "Keccak 256 Hash of the RLP encoding of a transaction", + "$ref": "#/components/schemas/Keccak" + }, + "Nonce": { + "title": "nonce", + "description": "A number only to be used once", + "$ref": "#/components/schemas/Integer" + }, + "From": { + "title": "From", + "description": "The sender of the transaction", + "$ref": "#/components/schemas/Address" + }, + "BlockNumberOrNull": { + "title": "blockNumberOrNull", + "description": "The block number or null when its the pending block", + "oneOf": [ + { + "$ref": "#/components/schemas/BlockNumber" + }, + { + "$ref": "#/components/schemas/Null" + } + ] + }, + "IntegerOrNull": { + "title": "integerOrNull", + "oneOf": [ + { + "$ref": "#/components/schemas/Integer" + }, + { + "$ref": "#/components/schemas/Null" + } + ] + }, + "KeccakOrPending": { + "title": "keccakOrPending", + "oneOf": [ + { + "$ref": "#/components/schemas/Keccak" + }, + { + "$ref": "#/components/schemas/Null" + } + ] + }, + "To": { + "title": "To", + "description": "Destination address of the transaction. Null if it was a contract create.", + "oneOf": [ + { + "$ref": "#/components/schemas/Address" + }, + { + "$ref": "#/components/schemas/Null" + } + ] + }, + "BlockHashOrNull": { + "title": "blockHashOrNull", + "description": "The block hash or null when its the pending block", + "$ref": "#/components/schemas/KeccakOrPending" + }, + "TransactionIndex": { + "title": "transactionIndex", + "description": "The index of the transaction. null when its pending", + "$ref": "#/components/schemas/IntegerOrNull" + }, + "Batch": { + "title": "Batch", + "type": "object", + "readOnly": true, + "properties": { + "number": { + "$ref": "#/components/schemas/BlockNumber" + }, + "transactions": { + "title": "transactionsOrHashes", + "description": "Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter", + "type": "array", + "items": { + "title": "transactionOrTransactionHash", + "oneOf": [ + { + "$ref": "#/components/schemas/Transaction" + }, + { + "$ref": "#/components/schemas/TransactionHash" + } + ] + } + }, + "globalExitRoot": { + "$ref": "#/components/schemas/Keccak" + }, + "mainnetExitRoot": { + "$ref": "#/components/schemas/Keccak" + }, + "rollupExitRoot": { + "$ref": "#/components/schemas/Keccak" + }, + "accInputHash": { + "$ref": "#/components/schemas/Keccak" + }, + "timestamp": { + "$ref": "#/components/schemas/Integer" + }, + "sendSequencesTxHash": { + "$ref": "#/components/schemas/TransactionHash" + }, + "verifyBatchTxHash": { + "$ref": "#/components/schemas/TransactionHash" + }, + "stateRoot": { + "$ref": "#/components/schemas/Keccak" + }, + "coinbase": { + "$ref": "#/components/schemas/Address" + } + } + }, + "Transaction": { + "title": "transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "nonce" + ], + "properties": { + "blockHash": { + "$ref": "#/components/schemas/BlockHashOrNull" + }, + "blockNumber": { + "$ref": "#/components/schemas/BlockNumberOrNull" + }, + "from": { + "$ref": "#/components/schemas/From" + }, + "gas": { + "title": "transactionGas", + "type": "string", + "description": "The gas limit provided by the sender in Wei" + }, + "gasPrice": { + "title": "transactionGasPrice", + "type": "string", + "description": "The gas price willing to be paid by the sender in Wei" + }, + "hash": { + "$ref": "#/components/schemas/TransactionHash" + }, + "input": { + "title": "transactionInput", + "type": "string", + "description": "The data field sent with the transaction" + }, + "nonce": { + "title": "transactionNonce", + "description": "The total number of prior transactions made by the sender", + "$ref": "#/components/schemas/Nonce" + }, + "to": { + "$ref": "#/components/schemas/To" + }, + "transactionIndex": { + "$ref": "#/components/schemas/TransactionIndex" + }, + "value": { + "title": "transactionValue", + "description": "Value of Ether being transferred in Wei", + "$ref": "#/components/schemas/Keccak" + }, + "v": { + "title": "transactionSigV", + "type": "string", + "description": "ECDSA recovery id" + }, + "r": { + "title": "transactionSigR", + "type": "string", + "description": "ECDSA signature r" + }, + "s": { + "title": "transactionSigS", + "type": "string", + "description": "ECDSA signature s" + } + } + }, + "Transactions": { + "title": "transactions", + "description": "An array of transactions", + "type": "array", + "items": { + "$ref": "#/components/schemas/Transaction" + } + } + } + } +} \ No newline at end of file diff --git a/jsonrpc/endpoints_zkevm_test.go b/jsonrpc/endpoints_zkevm_test.go new file mode 100644 index 0000000000..7f5564d625 --- /dev/null +++ b/jsonrpc/endpoints_zkevm_test.go @@ -0,0 +1,1136 @@ +package jsonrpc + +import ( + "context" + "encoding/json" + "errors" + "math/big" + "strings" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestConsolidatedBlockNumber(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult *uint64 + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "Get consolidated block number successfully", + ExpectedResult: ptrUint64(10), + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastConsolidatedL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + }, + }, + { + Name: "failed to get consolidated block number", + ExpectedResult: nil, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get last consolidated block number from state"), + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastConsolidatedL2BlockNumber", context.Background(), m.DbTx). + Return(uint64(0), errors.New("failed to get last consolidated block number")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_consolidatedBlockNumber") + require.NoError(t, err) + + if res.Result != nil { + var result types.ArgUint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, *tc.ExpectedResult, uint64(result)) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestIsBlockConsolidated(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult bool + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "Query status of block number successfully", + ExpectedResult: true, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("IsL2BlockConsolidated", context.Background(), uint64(1), m.DbTx). + Return(true, nil). + Once() + }, + }, + { + Name: "Failed to query the consolidation status", + ExpectedResult: false, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to check if the block is consolidated"), + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("IsL2BlockConsolidated", context.Background(), uint64(1), m.DbTx). + Return(false, errors.New("failed to check if the block is consolidated")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_isBlockConsolidated", "0x1") + require.NoError(t, err) + + if res.Result != nil { + var result bool + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, result) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestIsBlockVirtualized(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult bool + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "Query status of block number successfully", + ExpectedResult: true, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("IsL2BlockVirtualized", context.Background(), uint64(1), m.DbTx). + Return(true, nil). + Once() + }, + }, + { + Name: "Failed to query the virtualization status", + ExpectedResult: false, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to check if the block is virtualized"), + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("IsL2BlockVirtualized", context.Background(), uint64(1), m.DbTx). + Return(false, errors.New("failed to check if the block is virtualized")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_isBlockVirtualized", "0x1") + require.NoError(t, err) + + if res.Result != nil { + var result bool + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, result) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestBatchNumberByBlockNumber(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + blockNumber := uint64(1) + batchNumber := uint64(1) + + type testCase struct { + Name string + ExpectedResult *uint64 + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "get batch number by block number successfully", + ExpectedResult: &batchNumber, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("BatchNumberByL2BlockNumber", context.Background(), blockNumber, m.DbTx). + Return(batchNumber, nil). + Once() + }, + }, + { + Name: "failed to get batch number", + ExpectedResult: nil, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get batch number from block number"), + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("BatchNumberByL2BlockNumber", context.Background(), blockNumber, m.DbTx). + Return(uint64(0), errors.New("failed to get batch number of l2 batchNum")). + Once() + }, + }, + { + Name: "batch number not found", + ExpectedResult: nil, + ExpectedError: nil, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("BatchNumberByL2BlockNumber", context.Background(), blockNumber, m.DbTx). + Return(uint64(0), state.ErrNotFound). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_batchNumberByBlockNumber", hex.EncodeUint64(blockNumber)) + require.NoError(t, err) + + if tc.ExpectedResult != nil { + var result types.ArgUint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, *tc.ExpectedResult, uint64(result)) + } else { + if res.Result == nil { + assert.Nil(t, res.Result) + } else { + var result *uint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Nil(t, result) + } + } + + if tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } else { + assert.Nil(t, res.Error) + } + }) + } +} + +func TestBatchNumber(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult uint64 + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "get batch number successfully", + ExpectedError: nil, + ExpectedResult: 10, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastBatchNumber", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + }, + }, + { + Name: "failed to get batch number", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last batch number from state"), + ExpectedResult: 0, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastBatchNumber", context.Background(), m.DbTx). + Return(uint64(0), errors.New("failed to get last batch number")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_batchNumber") + require.NoError(t, err) + + if res.Result != nil { + var result types.ArgUint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, uint64(result)) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestVirtualBatchNumber(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult uint64 + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "get virtual batch number successfully", + ExpectedError: nil, + ExpectedResult: 10, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastVirtualBatchNum", context.Background(), m.DbTx). + Return(uint64(10), nil). + Once() + }, + }, + { + Name: "failed to get virtual batch number", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last virtual batch number from state"), + ExpectedResult: 0, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastVirtualBatchNum", context.Background(), m.DbTx). + Return(uint64(0), errors.New("failed to get last batch number")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_virtualBatchNumber") + require.NoError(t, err) + + if res.Result != nil { + var result types.ArgUint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, uint64(result)) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestVerifiedBatchNumber(t *testing.T) { + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + type testCase struct { + Name string + ExpectedResult uint64 + ExpectedError types.Error + SetupMocks func(m *mocksWrapper) + } + + testCases := []testCase{ + { + Name: "get verified batch number successfully", + ExpectedError: nil, + ExpectedResult: 10, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastVerifiedBatch", context.Background(), m.DbTx). + Return(&state.VerifiedBatch{BatchNumber: uint64(10)}, nil). + Once() + }, + }, + { + Name: "failed to get verified batch number", + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last verified batch number from state"), + ExpectedResult: 0, + SetupMocks: func(m *mocksWrapper) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastVerifiedBatch", context.Background(), m.DbTx). + Return(nil, errors.New("failed to get last batch number")). + Once() + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + tc.SetupMocks(m) + + res, err := s.JSONRPCCall("zkevm_verifiedBatchNumber") + require.NoError(t, err) + + if res.Result != nil { + var result types.ArgUint64 + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult, uint64(result)) + } + + if res.Error != nil || tc.ExpectedError != nil { + assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func TestGetBatchByNumber(t *testing.T) { + type testCase struct { + Name string + Number string + WithTxDetail bool + ExpectedResult *types.Batch + ExpectedError types.Error + SetupMocks func(*mockedServer, *mocksWrapper, *testCase) + } + + testCases := []testCase{ + { + Name: "Batch not found", + Number: "0x123", + ExpectedResult: nil, + ExpectedError: nil, + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetBatchByNumber", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(nil, state.ErrNotFound) + }, + }, + { + Name: "get specific batch successfully with tx detail", + Number: "0x345", + WithTxDetail: true, + ExpectedResult: &types.Batch{ + Number: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: 1, + SendSequencesTxHash: ptrHash(common.HexToHash("0x10")), + VerifyBatchTxHash: ptrHash(common.HexToHash("0x20")), + }, + ExpectedError: nil, + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + batch := &state.Batch{ + BatchNumber: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: time.Unix(1, 0), + } + + m.State. + On("GetBatchByNumber", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(batch, nil). + Once() + + virtualBatch := &state.VirtualBatch{ + TxHash: common.HexToHash("0x10"), + } + + m.State. + On("GetVirtualBatch", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(virtualBatch, nil). + Once() + + verifiedBatch := &state.VerifiedBatch{ + TxHash: common.HexToHash("0x20"), + } + + m.State. + On("GetVerifiedBatch", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(verifiedBatch, nil). + Once() + + ger := state.GlobalExitRoot{ + MainnetExitRoot: common.HexToHash("0x4"), + RollupExitRoot: common.HexToHash("0x4"), + GlobalExitRoot: common.HexToHash("0x4"), + } + m.State. + On("GetExitRootByGlobalExitRoot", context.Background(), batch.GlobalExitRoot, m.DbTx). + Return(&ger, nil). + Once() + + txs := []*ethTypes.Transaction{ + signTx(ethTypes.NewTransaction(1001, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + signTx(ethTypes.NewTransaction(1002, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + } + + batchTxs := make([]ethTypes.Transaction, 0, len(txs)) + + tc.ExpectedResult.Transactions = []types.TransactionOrHash{} + + for i, tx := range txs { + blockNumber := big.NewInt(int64(i)) + blockHash := common.HexToHash(hex.EncodeUint64(uint64(i))) + receipt := ethTypes.NewReceipt([]byte{}, false, uint64(0)) + receipt.TxHash = tx.Hash() + receipt.TransactionIndex = uint(i) + receipt.BlockNumber = blockNumber + receipt.BlockHash = blockHash + m.State. + On("GetTransactionReceipt", context.Background(), tx.Hash(), m.DbTx). + Return(receipt, nil). + Once() + + from, _ := state.GetSender(*tx) + V, R, S := tx.RawSignatureValues() + + tc.ExpectedResult.Transactions = append(tc.ExpectedResult.Transactions, + types.TransactionOrHash{ + Tx: &types.Transaction{ + Nonce: types.ArgUint64(tx.Nonce()), + GasPrice: types.ArgBig(*tx.GasPrice()), + Gas: types.ArgUint64(tx.Gas()), + To: tx.To(), + Value: types.ArgBig(*tx.Value()), + Input: tx.Data(), + Hash: tx.Hash(), + From: from, + BlockNumber: ptrArgUint64FromUint64(blockNumber.Uint64()), + BlockHash: ptrHash(receipt.BlockHash), + TxIndex: ptrArgUint64FromUint(receipt.TransactionIndex), + ChainID: types.ArgBig(*tx.ChainId()), + Type: types.ArgUint64(tx.Type()), + V: types.ArgBig(*V), + R: types.ArgBig(*R), + S: types.ArgBig(*S), + }, + }, + ) + + batchTxs = append(batchTxs, *tx) + } + m.State. + On("GetTransactionsByBatchNumber", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(batchTxs, nil). + Once() + }, + }, + { + Name: "get specific batch successfully without tx detail", + Number: "0x345", + WithTxDetail: false, + ExpectedResult: &types.Batch{ + Number: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: 1, + SendSequencesTxHash: ptrHash(common.HexToHash("0x10")), + VerifyBatchTxHash: ptrHash(common.HexToHash("0x20")), + }, + ExpectedError: nil, + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + batch := &state.Batch{ + BatchNumber: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: time.Unix(1, 0), + } + + m.State. + On("GetBatchByNumber", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(batch, nil). + Once() + + virtualBatch := &state.VirtualBatch{ + TxHash: common.HexToHash("0x10"), + } + + m.State. + On("GetVirtualBatch", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(virtualBatch, nil). + Once() + + verifiedBatch := &state.VerifiedBatch{ + TxHash: common.HexToHash("0x20"), + } + + m.State. + On("GetVerifiedBatch", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(verifiedBatch, nil). + Once() + + ger := state.GlobalExitRoot{ + MainnetExitRoot: common.HexToHash("0x4"), + RollupExitRoot: common.HexToHash("0x4"), + GlobalExitRoot: common.HexToHash("0x4"), + } + m.State. + On("GetExitRootByGlobalExitRoot", context.Background(), batch.GlobalExitRoot, m.DbTx). + Return(&ger, nil). + Once() + + txs := []*ethTypes.Transaction{ + signTx(ethTypes.NewTransaction(1001, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + signTx(ethTypes.NewTransaction(1002, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + } + + batchTxs := make([]ethTypes.Transaction, 0, len(txs)) + + tc.ExpectedResult.Transactions = []types.TransactionOrHash{} + + for i, tx := range txs { + blockNumber := big.NewInt(int64(i)) + blockHash := common.HexToHash(hex.EncodeUint64(uint64(i))) + receipt := ethTypes.NewReceipt([]byte{}, false, uint64(0)) + receipt.TxHash = tx.Hash() + receipt.TransactionIndex = uint(i) + receipt.BlockNumber = blockNumber + receipt.BlockHash = blockHash + m.State. + On("GetTransactionReceipt", context.Background(), tx.Hash(), m.DbTx). + Return(receipt, nil). + Once() + + tc.ExpectedResult.Transactions = append(tc.ExpectedResult.Transactions, + types.TransactionOrHash{ + Hash: state.HashPtr(tx.Hash()), + }, + ) + + batchTxs = append(batchTxs, *tx) + } + m.State. + On("GetTransactionsByBatchNumber", context.Background(), hex.DecodeBig(tc.Number).Uint64(), m.DbTx). + Return(batchTxs, nil). + Once() + }, + }, + { + Name: "get latest batch successfully", + Number: "latest", + WithTxDetail: true, + ExpectedResult: &types.Batch{ + Number: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: 1, + SendSequencesTxHash: ptrHash(common.HexToHash("0x10")), + VerifyBatchTxHash: ptrHash(common.HexToHash("0x20")), + }, + ExpectedError: nil, + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Commit", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastBatchNumber", context.Background(), m.DbTx). + Return(uint64(tc.ExpectedResult.Number), nil). + Once() + + batch := &state.Batch{ + BatchNumber: 1, + Coinbase: common.HexToAddress("0x1"), + StateRoot: common.HexToHash("0x2"), + AccInputHash: common.HexToHash("0x3"), + GlobalExitRoot: common.HexToHash("0x4"), + Timestamp: time.Unix(1, 0), + } + + m.State. + On("GetBatchByNumber", context.Background(), uint64(tc.ExpectedResult.Number), m.DbTx). + Return(batch, nil). + Once() + + virtualBatch := &state.VirtualBatch{ + TxHash: common.HexToHash("0x10"), + } + + m.State. + On("GetVirtualBatch", context.Background(), uint64(tc.ExpectedResult.Number), m.DbTx). + Return(virtualBatch, nil). + Once() + + verifiedBatch := &state.VerifiedBatch{ + TxHash: common.HexToHash("0x20"), + } + + m.State. + On("GetVerifiedBatch", context.Background(), uint64(tc.ExpectedResult.Number), m.DbTx). + Return(verifiedBatch, nil). + Once() + + ger := state.GlobalExitRoot{ + MainnetExitRoot: common.HexToHash("0x4"), + RollupExitRoot: common.HexToHash("0x4"), + GlobalExitRoot: common.HexToHash("0x4"), + } + m.State. + On("GetExitRootByGlobalExitRoot", context.Background(), batch.GlobalExitRoot, m.DbTx). + Return(&ger, nil). + Once() + + txs := []*ethTypes.Transaction{ + signTx(ethTypes.NewTransaction(1001, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + signTx(ethTypes.NewTransaction(1002, common.HexToAddress("0x1000"), big.NewInt(1000), 1001, big.NewInt(1002), []byte("1003")), s.ChainID()), + } + + batchTxs := make([]ethTypes.Transaction, 0, len(txs)) + + tc.ExpectedResult.Transactions = []types.TransactionOrHash{} + + for i, tx := range txs { + blockNumber := big.NewInt(int64(i)) + blockHash := common.HexToHash(hex.EncodeUint64(uint64(i))) + receipt := ethTypes.NewReceipt([]byte{}, false, uint64(0)) + receipt.TxHash = tx.Hash() + receipt.TransactionIndex = uint(i) + receipt.BlockNumber = blockNumber + receipt.BlockHash = blockHash + m.State. + On("GetTransactionReceipt", context.Background(), tx.Hash(), m.DbTx). + Return(receipt, nil). + Once() + + from, _ := state.GetSender(*tx) + V, R, S := tx.RawSignatureValues() + + tc.ExpectedResult.Transactions = append(tc.ExpectedResult.Transactions, + types.TransactionOrHash{ + Tx: &types.Transaction{ + Nonce: types.ArgUint64(tx.Nonce()), + GasPrice: types.ArgBig(*tx.GasPrice()), + Gas: types.ArgUint64(tx.Gas()), + To: tx.To(), + Value: types.ArgBig(*tx.Value()), + Input: tx.Data(), + Hash: tx.Hash(), + From: from, + BlockNumber: ptrArgUint64FromUint64(blockNumber.Uint64()), + BlockHash: ptrHash(receipt.BlockHash), + TxIndex: ptrArgUint64FromUint(receipt.TransactionIndex), + ChainID: types.ArgBig(*tx.ChainId()), + Type: types.ArgUint64(tx.Type()), + V: types.ArgBig(*V), + R: types.ArgBig(*R), + S: types.ArgBig(*S), + }, + }, + ) + + batchTxs = append(batchTxs, *tx) + } + m.State. + On("GetTransactionsByBatchNumber", context.Background(), uint64(tc.ExpectedResult.Number), m.DbTx). + Return(batchTxs, nil). + Once() + }, + }, + { + Name: "get latest batch fails to compute batch number", + Number: "latest", + ExpectedResult: nil, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "failed to get the last batch number from state"), + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastBatchNumber", context.Background(), m.DbTx). + Return(uint64(0), errors.New("failed to get last batch number")). + Once() + }, + }, + { + Name: "get latest batch fails to load batch by number", + Number: "latest", + ExpectedResult: nil, + ExpectedError: types.NewRPCError(types.DefaultErrorCode, "couldn't load batch from state by number 1"), + SetupMocks: func(s *mockedServer, m *mocksWrapper, tc *testCase) { + m.DbTx. + On("Rollback", context.Background()). + Return(nil). + Once() + + m.State. + On("BeginStateTransaction", context.Background()). + Return(m.DbTx, nil). + Once() + + m.State. + On("GetLastBatchNumber", context.Background(), m.DbTx). + Return(uint64(1), nil). + Once() + + m.State. + On("GetBatchByNumber", context.Background(), uint64(1), m.DbTx). + Return(nil, errors.New("failed to load batch by number")). + Once() + }, + }, + } + + s, m, _ := newSequencerMockedServer(t) + defer s.Stop() + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tc := testCase + testCase.SetupMocks(s, m, &tc) + + res, err := s.JSONRPCCall("zkevm_getBatchByNumber", tc.Number, tc.WithTxDetail) + require.NoError(t, err) + assert.Equal(t, float64(1), res.ID) + assert.Equal(t, "2.0", res.JSONRPC) + + if res.Result != nil { + var result interface{} + err = json.Unmarshal(res.Result, &result) + require.NoError(t, err) + + if result != nil || testCase.ExpectedResult != nil { + var batch map[string]interface{} + err = json.Unmarshal(res.Result, &batch) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedResult.Number.Hex(), batch["number"].(string)) + assert.Equal(t, tc.ExpectedResult.Coinbase.String(), batch["coinbase"].(string)) + assert.Equal(t, tc.ExpectedResult.StateRoot.String(), batch["stateRoot"].(string)) + assert.Equal(t, tc.ExpectedResult.GlobalExitRoot.String(), batch["globalExitRoot"].(string)) + assert.Equal(t, tc.ExpectedResult.LocalExitRoot.String(), batch["localExitRoot"].(string)) + assert.Equal(t, tc.ExpectedResult.AccInputHash.String(), batch["accInputHash"].(string)) + assert.Equal(t, tc.ExpectedResult.Timestamp.Hex(), batch["timestamp"].(string)) + assert.Equal(t, tc.ExpectedResult.SendSequencesTxHash.String(), batch["sendSequencesTxHash"].(string)) + assert.Equal(t, tc.ExpectedResult.VerifyBatchTxHash.String(), batch["verifyBatchTxHash"].(string)) + batchTxs := batch["transactions"].([]interface{}) + for i, txOrHash := range tc.ExpectedResult.Transactions { + switch batchTxOrHash := batchTxs[i].(type) { + case string: + assert.Equal(t, txOrHash.Hash.String(), batchTxOrHash) + case map[string]interface{}: + tx := txOrHash.Tx + assert.Equal(t, tx.Nonce.Hex(), batchTxOrHash["nonce"].(string)) + assert.Equal(t, tx.GasPrice.Hex(), batchTxOrHash["gasPrice"].(string)) + assert.Equal(t, tx.Gas.Hex(), batchTxOrHash["gas"].(string)) + assert.Equal(t, tx.To.String(), batchTxOrHash["to"].(string)) + assert.Equal(t, tx.Value.Hex(), batchTxOrHash["value"].(string)) + assert.Equal(t, tx.Input.Hex(), batchTxOrHash["input"].(string)) + assert.Equal(t, tx.V.Hex(), batchTxOrHash["v"].(string)) + assert.Equal(t, tx.R.Hex(), batchTxOrHash["r"].(string)) + assert.Equal(t, tx.S.Hex(), batchTxOrHash["s"].(string)) + assert.Equal(t, tx.Hash.String(), batchTxOrHash["hash"].(string)) + assert.Equal(t, strings.ToLower(tx.From.String()), strings.ToLower(batchTxOrHash["from"].(string))) + assert.Equal(t, tx.BlockHash.String(), batchTxOrHash["blockHash"].(string)) + assert.Equal(t, tx.BlockNumber.Hex(), batchTxOrHash["blockNumber"].(string)) + assert.Equal(t, tx.TxIndex.Hex(), batchTxOrHash["transactionIndex"].(string)) + assert.Equal(t, tx.ChainID.Hex(), batchTxOrHash["chainId"].(string)) + assert.Equal(t, tx.Type.Hex(), batchTxOrHash["type"].(string)) + } + } + } + } + + if res.Error != nil || testCase.ExpectedError != nil { + assert.Equal(t, testCase.ExpectedError.ErrorCode(), res.Error.Code) + assert.Equal(t, testCase.ExpectedError.Error(), res.Error.Message) + } + }) + } +} + +func ptrUint64(n uint64) *uint64 { + return &n +} + +func ptrArgUint64FromUint(n uint) *types.ArgUint64 { + tmp := types.ArgUint64(n) + return &tmp +} + +func ptrArgUint64FromUint64(n uint64) *types.ArgUint64 { + tmp := types.ArgUint64(n) + return &tmp +} + +func ptrHash(h common.Hash) *common.Hash { + return &h +} + +func signTx(tx *ethTypes.Transaction, chainID uint64) *ethTypes.Transaction { + privateKey, _ := crypto.GenerateKey() + auth, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(chainID)) + signedTx, _ := auth.Signer(auth.From, tx) + return signedTx +} diff --git a/jsonrpc/errors.go b/jsonrpc/errors.go deleted file mode 100644 index 9b89a1e7ee..0000000000 --- a/jsonrpc/errors.go +++ /dev/null @@ -1,42 +0,0 @@ -package jsonrpc - -import "fmt" - -const ( - defaultErrorCode = -32000 - invalidRequestErrorCode = -32600 - notFoundErrorCode = -32601 - invalidParamsErrorCode = -32602 - parserErrorCode = -32700 -) - -type rpcError interface { - Error() string - ErrorCode() int -} - -// RPCError represents an RPC error. -type RPCError struct { - err string - code int -} - -func newRPCError(code int, err string, args ...interface{}) *RPCError { - var errMessage string - if len(args) > 0 { - errMessage = fmt.Sprintf(err, args...) - } else { - errMessage = err - } - return &RPCError{code: code, err: errMessage} -} - -// Error returns the error message. -func (e *RPCError) Error() string { - return e.err -} - -// ErrorCode returns the error code. -func (e *RPCError) ErrorCode() int { - return e.code -} diff --git a/jsonrpc/errors_test.go b/jsonrpc/errors_test.go deleted file mode 100644 index 00b886660c..0000000000 --- a/jsonrpc/errors_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package jsonrpc - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestRPCErrorConstants(t *testing.T) { - assert.Equal(t, -32000, defaultErrorCode) - assert.Equal(t, -32600, invalidRequestErrorCode) - assert.Equal(t, -32601, notFoundErrorCode) - assert.Equal(t, -32602, invalidParamsErrorCode) - assert.Equal(t, -32700, parserErrorCode) -} - -func TestRPCErrorMethods(t *testing.T) { - const code, msg = 1, "err" - - var err rpcError = newRPCError(code, msg) - - assert.Equal(t, code, err.ErrorCode()) - assert.Equal(t, msg, err.Error()) -} diff --git a/jsonrpc/eth.go b/jsonrpc/eth.go deleted file mode 100644 index f3abb804f8..0000000000 --- a/jsonrpc/eth.go +++ /dev/null @@ -1,765 +0,0 @@ -package jsonrpc - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math/big" - - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/jackc/pgx/v4" -) - -// Eth contains implementations for the "eth" RPC endpoints -type Eth struct { - cfg Config - pool jsonRPCTxPool - state stateInterface - gpe gasPriceEstimator - storage storageInterface - txMan dbTxManager -} - -// BlockNumber returns current block number -func (e *Eth) BlockNumber() (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - lastBlockNumber, err := e.state.GetLastL2BlockNumber(ctx, dbTx) - if err != nil { - return "0x0", newRPCError(defaultErrorCode, "failed to get the last block number from state") - } - - return hex.EncodeUint64(lastBlockNumber), nil - }) -} - -// Call executes a new message call immediately and returns the value of -// executed contract and potential error. -// Note, this function doesn't make any changes in the state/blockchain and is -// useful to execute view/pure methods and retrieve values. -func (e *Eth) Call(arg *txnArgs, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - // If the caller didn't supply the gas limit in the message, then we set it to maximum possible => block gas limit - if arg.Gas == nil || *arg.Gas == argUint64(0) { - header, err := e.getBlockHeader(ctx, *number, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get block header", err) - } - - gas := argUint64(header.GasLimit) - arg.Gas = &gas - } - - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - sender, tx, err := arg.ToUnsignedTransaction(ctx, e.state, blockNumber, e.cfg, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to convert arguments into an unsigned transaction", err) - } - - var blockNumberToProcessTx *uint64 - if number != nil && *number != LatestBlockNumber && *number != PendingBlockNumber { - blockNumberToProcessTx = &blockNumber - } - - result := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockNumberToProcessTx, true, dbTx) - if result.Failed() { - return rpcErrorResponse(defaultErrorCode, result.Err.Error(), nil) - } - - return argBytesPtr(result.ReturnValue), nil - }) -} - -// ChainId returns the chain id of the client -func (e *Eth) ChainId() (interface{}, rpcError) { //nolint:revive - return hex.EncodeUint64(e.cfg.ChainID), nil -} - -// EstimateGas generates and returns an estimate of how much gas is necessary to -// allow the transaction to complete. -// The transaction will not be added to the blockchain. -// Note that the estimate may be significantly more than the amount of gas actually -// used by the transaction, for a variety of reasons including EVM mechanics and -// node performance. -func (e *Eth) EstimateGas(arg *txnArgs, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - sender, tx, err := arg.ToUnsignedTransaction(ctx, e.state, blockNumber, e.cfg, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to convert arguments into an unsigned transaction", err) - } - - var blockNumberToProcessTx *uint64 - if number != nil && *number != LatestBlockNumber && *number != PendingBlockNumber { - blockNumberToProcessTx = &blockNumber - } - - gasEstimation, err := e.state.EstimateGas(tx, sender, blockNumberToProcessTx, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, err.Error(), nil) - } - return hex.EncodeUint64(gasEstimation), nil - }) -} - -// GasPrice returns the average gas price based on the last x blocks -func (e *Eth) GasPrice() (interface{}, rpcError) { - ctx := context.Background() - gasPrice, err := e.gpe.GetAvgGasPrice(ctx) - if err != nil { - return "0x0", nil - } - if gasPrice != nil { - return hex.EncodeUint64(gasPrice.Uint64()), nil - } - return hex.EncodeUint64(0), nil -} - -// GetBalance returns the account's balance at the referenced block -func (e *Eth) GetBalance(address common.Address, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - balance, err := e.state.GetBalance(ctx, address, blockNumber, dbTx) - if errors.Is(err, state.ErrNotFound) { - return hex.EncodeUint64(0), nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get balance from state", err) - } - - return hex.EncodeBig(balance), nil - }) -} - -// GetBlockByHash returns information about a block by hash -func (e *Eth) GetBlockByHash(hash common.Hash, fullTx bool) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - block, err := e.state.GetL2BlockByHash(ctx, hash, dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get block by hash from state", err) - } - - rpcBlock := l2BlockToRPCBlock(block, fullTx) - - return rpcBlock, nil - }) -} - -// GetBlockByNumber returns information about a block by block number -func (e *Eth) GetBlockByNumber(number BlockNumber, fullTx bool) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - if number == PendingBlockNumber { - lastBlock, err := e.state.GetLastL2Block(ctx, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "couldn't load last block from state to compute the pending block", err) - } - header := types.CopyHeader(lastBlock.Header()) - header.ParentHash = lastBlock.Hash() - header.Number = big.NewInt(0).SetUint64(lastBlock.Number().Uint64() + 1) - header.TxHash = types.EmptyRootHash - header.UncleHash = types.EmptyUncleHash - block := types.NewBlockWithHeader(header) - rpcBlock := l2BlockToRPCBlock(block, fullTx) - - return rpcBlock, nil - } - var err error - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - block, err := e.state.GetL2BlockByNumber(ctx, blockNumber, dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, fmt.Sprintf("couldn't load block from state by number %v", blockNumber), err) - } - - rpcBlock := l2BlockToRPCBlock(block, fullTx) - - return rpcBlock, nil - }) -} - -// GetCode returns account code at given block number -func (e *Eth) GetCode(address common.Address, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - var err error - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - code, err := e.state.GetCode(ctx, address, blockNumber, dbTx) - if errors.Is(err, state.ErrNotFound) { - return "0x", nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get code", err) - } - - return argBytes(code), nil - }) -} - -// GetCompilers eth_getCompilers -func (e *Eth) GetCompilers() (interface{}, rpcError) { - return []interface{}{}, nil -} - -// GetFilterChanges polling method for a filter, which returns -// an array of logs which occurred since last poll. -func (e *Eth) GetFilterChanges(filterID argUint64) (interface{}, rpcError) { - filter, err := e.storage.GetFilter(uint64(filterID)) - if errors.Is(err, ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get filter from storage", err) - } - - switch filter.Type { - case FilterTypeBlock: - { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - res, err := e.state.GetL2BlockHashesSince(ctx, filter.LastPoll, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get block hashes", err) - } - rpcErr := e.updateFilterLastPoll(filter.ID) - if rpcErr != nil { - return nil, rpcErr - } - if len(res) == 0 { - return nil, nil - } - return res, nil - }) - } - case FilterTypePendingTx: - { - res, err := e.pool.GetPendingTxHashesSince(context.Background(), filter.LastPoll) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get pending transaction hashes", err) - } - rpcErr := e.updateFilterLastPoll(filter.ID) - if rpcErr != nil { - return nil, rpcErr - } - if len(res) == 0 { - return nil, nil - } - return res, nil - } - case FilterTypeLog: - { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - filterParameters := &LogFilter{} - err = json.Unmarshal([]byte(filter.Parameters), filterParameters) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to read filter parameters", err) - } - - filterParameters.Since = &filter.LastPoll - - resInterface, err := e.internalGetLogs(ctx, dbTx, filterParameters) - if err != nil { - return nil, err - } - rpcErr := e.updateFilterLastPoll(filter.ID) - if rpcErr != nil { - return nil, rpcErr - } - res := resInterface.([]rpcLog) - if len(res) == 0 { - return nil, nil - } - return res, nil - }) - } - default: - return nil, nil - } -} - -// GetFilterLogs returns an array of all logs mlocking filter -// with given id. -func (e *Eth) GetFilterLogs(filterID argUint64) (interface{}, rpcError) { - filter, err := e.storage.GetFilter(uint64(filterID)) - if errors.Is(err, ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get filter from storage", err) - } - - if filter.Type != FilterTypeLog { - return nil, nil - } - - filterParameters := &LogFilter{} - err = json.Unmarshal([]byte(filter.Parameters), filterParameters) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to read filter parameters", err) - } - - filterParameters.Since = nil - - return e.GetLogs(filterParameters) -} - -// GetLogs returns a list of logs accordingly to the provided filter -func (e *Eth) GetLogs(filter *LogFilter) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - return e.internalGetLogs(ctx, dbTx, filter) - }) -} - -func (e *Eth) internalGetLogs(ctx context.Context, dbTx pgx.Tx, filter *LogFilter) (interface{}, rpcError) { - var err error - fromBlock, rpcErr := filter.FromBlock.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - toBlock, rpcErr := filter.ToBlock.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - logs, err := e.state.GetLogs(ctx, fromBlock, toBlock, filter.Addresses, filter.Topics, filter.BlockHash, filter.Since, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get logs from state", err) - } - - result := make([]rpcLog, 0, len(logs)) - for _, l := range logs { - result = append(result, logToRPCLog(*l)) - } - - return result, nil -} - -// GetStorageAt gets the value stored for an specific address and position -func (e *Eth) GetStorageAt(address common.Address, position common.Hash, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - var err error - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - value, err := e.state.GetStorageAt(ctx, address, position.Big(), blockNumber, dbTx) - if errors.Is(err, state.ErrNotFound) { - return argBytesPtr(common.Hash{}.Bytes()), nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get storage value from state", err) - } - - return argBytesPtr(common.BigToHash(value).Bytes()), nil - }) -} - -// GetTransactionByBlockHashAndIndex returns information about a transaction by -// block hash and transaction index position. -func (e *Eth) GetTransactionByBlockHashAndIndex(hash common.Hash, index Index) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - tx, err := e.state.GetTransactionByL2BlockHashAndIndex(ctx, hash, uint64(index), dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get transaction", err) - } - - receipt, err := e.state.GetTransactionReceipt(ctx, tx.Hash(), dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get transaction receipt", err) - } - - txIndex := uint64(receipt.TransactionIndex) - return toRPCTransaction(tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil - }) -} - -// GetTransactionByBlockNumberAndIndex returns information about a transaction by -// block number and transaction index position. -func (e *Eth) GetTransactionByBlockNumberAndIndex(number *BlockNumber, index Index) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - var err error - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - tx, err := e.state.GetTransactionByL2BlockNumberAndIndex(ctx, blockNumber, uint64(index), dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get transaction", err) - } - - receipt, err := e.state.GetTransactionReceipt(ctx, tx.Hash(), dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get transaction receipt", err) - } - - txIndex := uint64(receipt.TransactionIndex) - return toRPCTransaction(tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil - }) -} - -// GetTransactionByHash returns a transaction by his hash -func (e *Eth) GetTransactionByHash(hash common.Hash) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - // try to get tx from state - tx, err := e.state.GetTransactionByHash(ctx, hash, dbTx) - if err != nil && !errors.Is(err, state.ErrNotFound) { - return rpcErrorResponse(defaultErrorCode, "failed to load transaction by hash from state", err) - } - if tx != nil { - receipt, err := e.state.GetTransactionReceipt(ctx, hash, dbTx) - if errors.Is(err, state.ErrNotFound) { - return rpcErrorResponse(defaultErrorCode, "transaction receipt not found", err) - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to load transaction receipt from state", err) - } - - txIndex := uint64(receipt.TransactionIndex) - return toRPCTransaction(tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex), nil - } - - // if the tx does not exist in the state, look for it in the pool - poolTx, err := e.pool.GetTxByHash(ctx, hash) - if errors.Is(err, pgpoolstorage.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to load transaction by hash from pool", err) - } - tx = &poolTx.Transaction - - return toRPCTransaction(tx, nil, nil, nil), nil - }) -} - -// GetTransactionCount returns account nonce -func (e *Eth) GetTransactionCount(address common.Address, number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - var pendingNonce uint64 - var nonce uint64 - var err error - if number != nil && *number == PendingBlockNumber { - pendingNonce, err = e.pool.GetNonce(ctx, address) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to count pending transactions", err) - } - } - - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - nonce, err = e.state.GetNonce(ctx, address, blockNumber, dbTx) - - if errors.Is(err, state.ErrNotFound) { - return hex.EncodeUint64(0), nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to count transactions", err) - } - - if pendingNonce > nonce { - nonce = pendingNonce - } - - return hex.EncodeUint64(nonce), nil - }) -} - -// GetBlockTransactionCountByHash returns the number of transactions in a -// block from a block mlocking the given block hash. -func (e *Eth) GetBlockTransactionCountByHash(hash common.Hash) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - c, err := e.state.GetL2BlockTransactionCountByHash(ctx, hash, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to count transactions", err) - } - - return argUint64(c), nil - }) -} - -// GetBlockTransactionCountByNumber returns the number of transactions in a -// block from a block mlocking the given block number. -func (e *Eth) GetBlockTransactionCountByNumber(number *BlockNumber) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - if number != nil && *number == PendingBlockNumber { - c, err := e.pool.CountPendingTransactions(ctx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to count pending transactions", err) - } - return argUint64(c), nil - } - - var err error - blockNumber, rpcErr := number.getNumericBlockNumber(ctx, e.state, dbTx) - if rpcErr != nil { - return nil, rpcErr - } - - c, err := e.state.GetL2BlockTransactionCountByNumber(ctx, blockNumber, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to count transactions", err) - } - - return argUint64(c), nil - }) -} - -// GetTransactionReceipt returns a transaction receipt by his hash -func (e *Eth) GetTransactionReceipt(hash common.Hash) (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - tx, err := e.state.GetTransactionByHash(ctx, hash, dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get tx from state", err) - } - - r, err := e.state.GetTransactionReceipt(ctx, hash, dbTx) - if errors.Is(err, state.ErrNotFound) { - return nil, nil - } else if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get tx receipt from state", err) - } - - receipt, err := receiptToRPCReceipt(*tx, r) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to build the receipt response", err) - } - - return receipt, nil - }) -} - -// NewBlockFilter creates a filter in the node, to notify when -// a new block arrives. To check if the state has changed, -// call eth_getFilterChanges. -func (e *Eth) NewBlockFilter() (interface{}, rpcError) { - id, err := e.storage.NewBlockFilter() - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to create new block filter", err) - } - - return argUint64(id), nil -} - -// NewFilter creates a filter object, based on filter options, -// to notify when the state changes (logs). To check if the state -// has changed, call eth_getFilterChanges. -func (e *Eth) NewFilter(filter *LogFilter) (interface{}, rpcError) { - id, err := e.storage.NewLogFilter(*filter) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to create new log filter", err) - } - - return argUint64(id), nil -} - -// NewPendingTransactionFilter creates a filter in the node, to -// notify when new pending transactions arrive. To check if the -// state has changed, call eth_getFilterChanges. -func (e *Eth) NewPendingTransactionFilter(filterID argUint64) (interface{}, rpcError) { - id, err := e.storage.NewPendingTransactionFilter() - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to create new pending transaction filter", err) - } - - return argUint64(id), nil -} - -// SendRawTransaction has two different ways to handle new transactions: -// - for Sequencer nodes it tries to add the tx to the pool -// - for Non-Sequencer nodes it relays the Tx to the Sequencer node -func (e *Eth) SendRawTransaction(input string) (interface{}, rpcError) { - if e.cfg.SequencerNodeURI != "" { - return e.relayTxToSequencerNode(input) - } else { - return e.tryToAddTxToPool(input) - } -} - -func (e *Eth) relayTxToSequencerNode(input string) (interface{}, rpcError) { - res, err := JSONRPCCall(e.cfg.SequencerNodeURI, "eth_sendRawTransaction", input) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to relay tx to the sequencer node", err) - } - - if res.Error != nil { - return rpcErrorResponse(res.Error.Code, res.Error.Message, nil) - } - - txHash := res.Result - - return txHash, nil -} - -func (e *Eth) tryToAddTxToPool(input string) (interface{}, rpcError) { - tx, err := hexToTx(input) - if err != nil { - return rpcErrorResponse(invalidParamsErrorCode, "invalid tx input", err) - } - - log.Debugf("adding TX to the pool: %v", tx.Hash().Hex()) - if err := e.pool.AddTx(context.Background(), *tx); err != nil { - return rpcErrorResponse(defaultErrorCode, err.Error(), nil) - } - log.Infof("TX added to the pool: %v", tx.Hash().Hex()) - - return tx.Hash().Hex(), nil -} - -// UninstallFilter uninstalls a filter with given id. Should -// always be called when wlock is no longer needed. Additionally -// Filters timeout when they aren’t requested with -// eth_getFilterChanges for a period of time. -func (e *Eth) UninstallFilter(filterID argUint64) (interface{}, rpcError) { - uninstalled, err := e.storage.UninstallFilter(uint64(filterID)) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to uninstall filter", err) - } - - return uninstalled, nil -} - -// Syncing returns an object with data about the sync status or false. -// https://eth.wiki/json-rpc/API#eth_syncing -func (e *Eth) Syncing() (interface{}, rpcError) { - return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - syncInfo, err := e.state.GetSyncingInfo(ctx, dbTx) - if err != nil { - return rpcErrorResponse(defaultErrorCode, "failed to get syncing info from state", err) - } - - if syncInfo.CurrentBlockNumber == syncInfo.LastBlockNumberSeen { - return false, nil - } - - return struct { - S argUint64 `json:"startingBlock"` - C argUint64 `json:"currentBlock"` - H argUint64 `json:"highestBlock"` - }{ - S: argUint64(syncInfo.InitialSyncingBlock), - C: argUint64(syncInfo.CurrentBlockNumber), - H: argUint64(syncInfo.LastBlockNumberSeen), - }, nil - }) -} - -// GetUncleByBlockHashAndIndex returns information about a uncle of a -// block by hash and uncle index position -func (e *Eth) GetUncleByBlockHashAndIndex() (interface{}, rpcError) { - return nil, nil -} - -// GetUncleByBlockNumberAndIndex returns information about a uncle of a -// block by number and uncle index position -func (e *Eth) GetUncleByBlockNumberAndIndex() (interface{}, rpcError) { - return nil, nil -} - -// GetUncleCountByBlockHash returns the number of uncles in a block -// mlocking the given block hash -func (e *Eth) GetUncleCountByBlockHash() (interface{}, rpcError) { - return "0x0", nil -} - -// GetUncleCountByBlockNumber returns the number of uncles in a block -// mlocking the given block number -func (e *Eth) GetUncleCountByBlockNumber() (interface{}, rpcError) { - return "0x0", nil -} - -// ProtocolVersion returns the protocol version. -func (e *Eth) ProtocolVersion() (interface{}, rpcError) { - return "0x0", nil -} - -func hexToTx(str string) (*types.Transaction, error) { - tx := new(types.Transaction) - - b, err := hex.DecodeHex(str) - if err != nil { - return nil, err - } - - if err := tx.UnmarshalBinary(b); err != nil { - return nil, err - } - - return tx, nil -} - -func (e *Eth) getBlockHeader(ctx context.Context, number BlockNumber, dbTx pgx.Tx) (*types.Header, error) { - switch number { - case LatestBlockNumber: - block, err := e.state.GetLastL2Block(ctx, dbTx) - if err != nil { - return nil, err - } - return block.Header(), nil - - case EarliestBlockNumber: - header, err := e.state.GetL2BlockHeaderByNumber(ctx, uint64(0), dbTx) - if err != nil { - return nil, err - } - return header, nil - - case PendingBlockNumber: - lastBlock, err := e.state.GetLastL2Block(ctx, dbTx) - if err != nil { - return nil, err - } - parentHash := lastBlock.Hash() - number := lastBlock.Number().Uint64() + 1 - - header := &types.Header{ - ParentHash: parentHash, - Number: big.NewInt(0).SetUint64(number), - Difficulty: big.NewInt(0), - GasLimit: lastBlock.Header().GasLimit, - } - return header, nil - - default: - return e.state.GetL2BlockHeaderByNumber(ctx, uint64(number), dbTx) - } -} - -func (e *Eth) updateFilterLastPoll(filterID uint64) rpcError { - err := e.storage.UpdateFilterLastPoll(filterID) - if err != nil { - return newRPCError(defaultErrorCode, "failed to update last time the filter changes were requested") - } - return nil -} diff --git a/jsonrpc/handler.go b/jsonrpc/handler.go index 0db07f88d5..d0b3e15dee 100644 --- a/jsonrpc/handler.go +++ b/jsonrpc/handler.go @@ -3,12 +3,15 @@ package jsonrpc import ( "encoding/json" "fmt" + "net/http" "reflect" "strings" "sync" "unicode" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/gorilla/websocket" ) const ( @@ -31,7 +34,34 @@ func (f *funcData) numParams() int { return f.inNum - 1 } -// Handler handles jsonrpc requests +type handleRequest struct { + types.Request + wsConn *websocket.Conn + HttpRequest *http.Request +} + +// Handler manage services to handle jsonrpc requests +// +// Services are public structures containing public methods +// matching the name of the jsonrpc method. +// +// Services must be registered with a prefix to identify the +// service and its methods, for example a service registered +// with a prefix `eth` will have all the public methods exposed +// as eth_ through the json rpc server. +// +// Go public methods requires the first char of its name to be +// in uppercase, but the exposition of the method will consider +// it to lower case, for example a method `func MyMethod()` +// provided by the service registered with `eth` prefix will +// be triggered when the method eth_myMethod is specified +// +// the public methods must follow the conventions: +// - return interface{}, rpcError +// - if the method depend on a Web Socket connection, it must be the first parameters as f(*websocket.Conn) +// - parameter types must match the type of the data provided for the method +// +// check the `eth.go` file for more example on how the methods are implemented type Handler struct { serviceMap map[string]*serviceData } @@ -48,7 +78,8 @@ var connectionCounterMutex sync.Mutex // Handle is the function that knows which and how a function should // be executed when a JSON RPC request is received -func (d *Handler) Handle(req Request) Response { +func (h *Handler) Handle(req handleRequest) types.Response { + log := log.WithFields("method", req.Method, "requestId", req.ID) connectionCounterMutex.Lock() connectionCounter++ connectionCounterMutex.Unlock() @@ -59,46 +90,112 @@ func (d *Handler) Handle(req Request) Response { log.Debugf("Current open connections %d", connectionCounter) }() log.Debugf("Current open connections %d", connectionCounter) - log.Debugf("request method %s id %v params %v", req.Method, req.ID, string(req.Params)) + log.Debugf("request params %v", string(req.Params)) - service, fd, err := d.getFnHandler(req) + service, fd, err := h.getFnHandler(req.Request) if err != nil { - return NewResponse(req, nil, err) + return types.NewResponse(req.Request, nil, err) } + inArgsOffset := 0 inArgs := make([]reflect.Value, fd.inNum) inArgs[0] = service.sv - inputs := make([]interface{}, fd.numParams()) - for i := 0; i < fd.inNum-1; i++ { + requestHasWebSocketConn := req.wsConn != nil + funcHasMoreThanOneInputParams := len(fd.reqt) > 1 + firstFuncParamIsWebSocketConn := false + firstFuncParamIsHttpRequest := false + if funcHasMoreThanOneInputParams { + firstFuncParamIsWebSocketConn = fd.reqt[1].AssignableTo(reflect.TypeOf(&websocket.Conn{})) + firstFuncParamIsHttpRequest = fd.reqt[1].AssignableTo(reflect.TypeOf(&http.Request{})) + } + if requestHasWebSocketConn && firstFuncParamIsWebSocketConn { + inArgs[1] = reflect.ValueOf(req.wsConn) + inArgsOffset++ + } else if firstFuncParamIsHttpRequest { + // If in the future one endponit needs to have both a websocket connection and an http request + // we will need to modify this code to properly handle it + inArgs[1] = reflect.ValueOf(req.HttpRequest) + inArgsOffset++ + } + + // check params passed by request match function params + var testStruct []interface{} + if err := json.Unmarshal(req.Params, &testStruct); err == nil && len(testStruct) > fd.numParams() { + return types.NewResponse(req.Request, nil, types.NewRPCError(types.InvalidParamsErrorCode, fmt.Sprintf("too many arguments, want at most %d", fd.numParams()))) + } + + inputs := make([]interface{}, fd.numParams()-inArgsOffset) + + for i := inArgsOffset; i < fd.inNum-1; i++ { val := reflect.New(fd.reqt[i+1]) - inputs[i] = val.Interface() + inputs[i-inArgsOffset] = val.Interface() inArgs[i+1] = val.Elem() } if fd.numParams() > 0 { if err := json.Unmarshal(req.Params, &inputs); err != nil { - return NewResponse(req, nil, newRPCError(invalidParamsErrorCode, "Invalid Params")) + return types.NewResponse(req.Request, nil, types.NewRPCError(types.InvalidParamsErrorCode, "Invalid Params")) } } output := fd.fv.Call(inArgs) if err := getError(output[1]); err != nil { - log.Errorf("failed to call method %s: [%v]%v. Params: %v", req.Method, err.ErrorCode(), err.Error(), string(req.Params)) - return NewResponse(req, nil, err) + log.Infof("failed call: [%v]%v. Params: %v", err.ErrorCode(), err.Error(), string(req.Params)) + return types.NewResponse(req.Request, nil, err) } - var data *[]byte + var data []byte res := output[0].Interface() if res != nil { d, _ := json.Marshal(res) - data = &d + data = d + } + + return types.NewResponse(req.Request, data, nil) +} + +// HandleWs handle websocket requests +func (h *Handler) HandleWs(reqBody []byte, wsConn *websocket.Conn) ([]byte, error) { + var req types.Request + if err := json.Unmarshal(reqBody, &req); err != nil { + return types.NewResponse(req, nil, types.NewRPCError(types.InvalidRequestErrorCode, "Invalid json request")).Bytes() + } + + handleReq := handleRequest{ + Request: req, + wsConn: wsConn, } - return NewResponse(req, data, nil) + return h.Handle(handleReq).Bytes() +} + +// RemoveFilterByWsConn uninstalls the filter attached to this websocket connection +func (h *Handler) RemoveFilterByWsConn(wsConn *websocket.Conn) { + service, ok := h.serviceMap[APIEth] + if !ok { + return + } + + ethEndpointsInterface := service.sv.Interface() + if ethEndpointsInterface == nil { + log.Errorf("failed to get ETH endpoint interface") + } + + ethEndpoints := ethEndpointsInterface.(*EthEndpoints) + if ethEndpoints == nil { + log.Errorf("failed to get ETH endpoint instance") + return + } + + err := ethEndpoints.uninstallFilterByWSConn(wsConn) + if err != nil { + log.Errorf("failed to uninstall filter by web socket connection:, %v", err) + return + } } -func (d *Handler) registerService(serviceName string, service interface{}) { +func (h *Handler) registerService(serviceName string, service interface{}) { st := reflect.TypeOf(service) if st.Kind() == reflect.Struct { panic(fmt.Sprintf("jsonrpc: service '%s' must be a pointer to struct", serviceName)) @@ -131,37 +228,37 @@ func (d *Handler) registerService(serviceName string, service interface{}) { funcMap[name] = fd } - d.serviceMap[serviceName] = &serviceData{ + h.serviceMap[serviceName] = &serviceData{ sv: reflect.ValueOf(service), funcMap: funcMap, } } -func (d *Handler) getFnHandler(req Request) (*serviceData, *funcData, rpcError) { +func (h *Handler) getFnHandler(req types.Request) (*serviceData, *funcData, types.Error) { methodNotFoundErrorMessage := fmt.Sprintf("the method %s does not exist/is not available", req.Method) callName := strings.SplitN(req.Method, "_", 2) //nolint:gomnd if len(callName) != 2 { //nolint:gomnd - return nil, nil, newRPCError(notFoundErrorCode, methodNotFoundErrorMessage) + return nil, nil, types.NewRPCError(types.NotFoundErrorCode, methodNotFoundErrorMessage) } serviceName, funcName := callName[0], callName[1] - service, ok := d.serviceMap[serviceName] + service, ok := h.serviceMap[serviceName] if !ok { log.Infof("Method %s not found", req.Method) - return nil, nil, newRPCError(notFoundErrorCode, methodNotFoundErrorMessage) + return nil, nil, types.NewRPCError(types.NotFoundErrorCode, methodNotFoundErrorMessage) } fd, ok := service.funcMap[funcName] if !ok { - return nil, nil, newRPCError(notFoundErrorCode, methodNotFoundErrorMessage) + return nil, nil, types.NewRPCError(types.NotFoundErrorCode, methodNotFoundErrorMessage) } return service, fd, nil } func validateFunc(funcName string, fv reflect.Value, isMethod bool) (inNum int, reqt []reflect.Type, err error) { if funcName == "" { - err = fmt.Errorf("funcName cannot be empty") + err = fmt.Errorf("getBlockNumByArg cannot be empty") return } @@ -190,22 +287,22 @@ func validateFunc(funcName string, fv reflect.Value, isMethod bool) (inNum int, return } -var rpcErrType = reflect.TypeOf((*rpcError)(nil)).Elem() +var rpcErrType = reflect.TypeOf((*types.Error)(nil)).Elem() func isRPCErrorType(t reflect.Type) bool { return t.Implements(rpcErrType) } -func getError(v reflect.Value) rpcError { +func getError(v reflect.Value) types.Error { if v.IsNil() { return nil } switch vt := v.Interface().(type) { - case *RPCError: + case *types.RPCError: return vt default: - return newRPCError(defaultErrorCode, "runtime error") + return types.NewRPCError(types.DefaultErrorCode, "runtime error") } } diff --git a/jsonrpc/interfaces.go b/jsonrpc/interfaces.go index 0d03899e54..f1fce40123 100644 --- a/jsonrpc/interfaces.go +++ b/jsonrpc/interfaces.go @@ -1,69 +1,18 @@ package jsonrpc import ( - "context" - "math/big" - "time" - - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/state/runtime" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/jackc/pgx/v4" + "github.com/gorilla/websocket" ) -// jsonRPCTxPool contains the methods required to interact with the tx pool. -type jsonRPCTxPool interface { - AddTx(ctx context.Context, tx types.Transaction) error - GetGasPrice(ctx context.Context) (uint64, error) - GetNonce(ctx context.Context, address common.Address) (uint64, error) - GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) - GetPendingTxs(ctx context.Context, isClaims bool, limit uint64) ([]pool.Transaction, error) - CountPendingTransactions(ctx context.Context) (uint64, error) - GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Transaction, error) -} - -// gasPriceEstimator contains the methods required to interact with gas price estimator -type gasPriceEstimator interface { - GetAvgGasPrice(ctx context.Context) (*big.Int, error) -} - -// stateInterface gathers the methods required to interact with the state. -type stateInterface interface { - BeginStateTransaction(ctx context.Context) (pgx.Tx, error) - DebugTransaction(ctx context.Context, transactionHash common.Hash, tracer string, dbTx pgx.Tx) (*runtime.ExecutionResult, error) - EstimateGas(transaction *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, error) - GetBalance(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) - GetCode(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) ([]byte, error) - GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*types.Block, error) - GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Block, error) - GetL2BlockHashesSince(ctx context.Context, since time.Time, dbTx pgx.Tx) ([]common.Hash, error) - GetL2BlockHeaderByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Header, error) - GetL2BlockTransactionCountByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (uint64, error) - GetL2BlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) - GetLastConsolidatedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) - GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) - GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) - GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) - GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*types.Log, error) - GetNonce(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (uint64, error) - GetStorageAt(ctx context.Context, address common.Address, position *big.Int, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) - GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (state.SyncingInfo, error) - GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) - GetTransactionByL2BlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) - GetTransactionByL2BlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) - GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Receipt, error) - IsL2BlockConsolidated(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) - IsL2BlockVirtualized(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) - ProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) *runtime.ExecutionResult -} - +// storageInterface json rpc internal storage to persist data type storageInterface interface { - GetFilter(filterID uint64) (*Filter, error) - NewBlockFilter() (uint64, error) - NewLogFilter(filter LogFilter) (uint64, error) - NewPendingTransactionFilter() (uint64, error) - UninstallFilter(filterID uint64) (bool, error) - UpdateFilterLastPoll(filterID uint64) error + GetAllBlockFiltersWithWSConn() ([]*Filter, error) + GetAllLogFiltersWithWSConn() ([]*Filter, error) + GetFilter(filterID string) (*Filter, error) + NewBlockFilter(wsConn *websocket.Conn) (string, error) + NewLogFilter(wsConn *websocket.Conn, filter LogFilter) (string, error) + NewPendingTransactionFilter(wsConn *websocket.Conn) (string, error) + UninstallFilter(filterID string) error + UninstallFilterByWSConn(wsConn *websocket.Conn) error + UpdateFilterLastPoll(filterID string) error } diff --git a/jsonrpc/metrics/metrics.go b/jsonrpc/metrics/metrics.go new file mode 100644 index 0000000000..4ffefca2a1 --- /dev/null +++ b/jsonrpc/metrics/metrics.go @@ -0,0 +1,74 @@ +package metrics + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + prefix = "jsonrpc_" + requestPrefix = prefix + "request_" + requestsHandledName = requestPrefix + "handled" + requestDurationName = requestPrefix + "duration" + + requestHandledTypeLabelName = "type" +) + +// RequestHandledLabel represents the possible values for the +// `jsonrpc_request_handled` metric `type` label. +type RequestHandledLabel string + +const ( + // RequestHandledLabelInvalid represents an request of type invalid + RequestHandledLabelInvalid RequestHandledLabel = "invalid" + // RequestHandledLabelSingle represents an request of type single + RequestHandledLabelSingle RequestHandledLabel = "single" + // RequestHandledLabelBatch represents an request of type batch + RequestHandledLabelBatch RequestHandledLabel = "batch" +) + +// Register the metrics for the jsonrpc package. +func Register() { + var ( + counterVecs []metrics.CounterVecOpts + histograms []prometheus.HistogramOpts + ) + + counterVecs = []metrics.CounterVecOpts{ + { + CounterOpts: prometheus.CounterOpts{ + Name: requestsHandledName, + Help: "[JSONRPC] number of requests handled", + }, + Labels: []string{requestHandledTypeLabelName}, + }, + } + + start := 0.1 + width := 0.1 + count := 10 + histograms = []prometheus.HistogramOpts{ + { + Name: requestDurationName, + Help: "[JSONRPC] Histogram for the runtime of requests", + Buckets: prometheus.LinearBuckets(start, width, count), + }, + } + + metrics.RegisterCounterVecs(counterVecs...) + metrics.RegisterHistograms(histograms...) +} + +// RequestHandled increments the requests handled counter vector by one for the +// given label. +func RequestHandled(label RequestHandledLabel) { + metrics.CounterVecInc(requestsHandledName, string(label)) +} + +// RequestDuration observes (histogram) the duration of a request from the +// provided starting time. +func RequestDuration(start time.Time) { + metrics.HistogramObserve(requestDurationName, time.Since(start).Seconds()) +} diff --git a/jsonrpc/mock_gasPriceEstimator_test.go b/jsonrpc/mock_gasPriceEstimator_test.go deleted file mode 100644 index acb9420a9c..0000000000 --- a/jsonrpc/mock_gasPriceEstimator_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package jsonrpc - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// gasPriceEstimatorMock is an autogenerated mock type for the gasPriceEstimator type -type gasPriceEstimatorMock struct { - mock.Mock -} - -// GetAvgGasPrice provides a mock function with given fields: ctx -func (_m *gasPriceEstimatorMock) GetAvgGasPrice(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - var r0 *big.Int - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTnewGasPriceEstimatorMock interface { - mock.TestingT - Cleanup(func()) -} - -// newGasPriceEstimatorMock creates a new instance of gasPriceEstimatorMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func newGasPriceEstimatorMock(t mockConstructorTestingTnewGasPriceEstimatorMock) *gasPriceEstimatorMock { - mock := &gasPriceEstimatorMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/jsonrpc/mock_state_test.go b/jsonrpc/mock_state_test.go deleted file mode 100644 index ccd2ef7f79..0000000000 --- a/jsonrpc/mock_state_test.go +++ /dev/null @@ -1,615 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package jsonrpc - -import ( - context "context" - big "math/big" - - common "github.com/ethereum/go-ethereum/common" - - mock "github.com/stretchr/testify/mock" - - pgx "github.com/jackc/pgx/v4" - - runtime "github.com/0xPolygonHermez/zkevm-node/state/runtime" - - state "github.com/0xPolygonHermez/zkevm-node/state" - - time "time" - - types "github.com/ethereum/go-ethereum/core/types" -) - -// stateMock is an autogenerated mock type for the stateInterface type -type stateMock struct { - mock.Mock -} - -// BeginStateTransaction provides a mock function with given fields: ctx -func (_m *stateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { - ret := _m.Called(ctx) - - var r0 pgx.Tx - if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(pgx.Tx) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// DebugTransaction provides a mock function with given fields: ctx, transactionHash, tracer, dbTx -func (_m *stateMock) DebugTransaction(ctx context.Context, transactionHash common.Hash, tracer string, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { - ret := _m.Called(ctx, transactionHash, tracer, dbTx) - - var r0 *runtime.ExecutionResult - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, string, pgx.Tx) *runtime.ExecutionResult); ok { - r0 = rf(ctx, transactionHash, tracer, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*runtime.ExecutionResult) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, string, pgx.Tx) error); ok { - r1 = rf(ctx, transactionHash, tracer, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EstimateGas provides a mock function with given fields: transaction, senderAddress, l2BlockNumber, dbTx -func (_m *stateMock) EstimateGas(transaction *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(transaction, senderAddress, l2BlockNumber, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(*types.Transaction, common.Address, *uint64, pgx.Tx) uint64); ok { - r0 = rf(transaction, senderAddress, l2BlockNumber, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(*types.Transaction, common.Address, *uint64, pgx.Tx) error); ok { - r1 = rf(transaction, senderAddress, l2BlockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetBalance provides a mock function with given fields: ctx, address, blockNumber, dbTx -func (_m *stateMock) GetBalance(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) { - ret := _m.Called(ctx, address, blockNumber, dbTx) - - var r0 *big.Int - if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64, pgx.Tx) *big.Int); ok { - r0 = rf(ctx, address, blockNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Address, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, address, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetCode provides a mock function with given fields: ctx, address, blockNumber, dbTx -func (_m *stateMock) GetCode(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) ([]byte, error) { - ret := _m.Called(ctx, address, blockNumber, dbTx) - - var r0 []byte - if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64, pgx.Tx) []byte); ok { - r0 = rf(ctx, address, blockNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Address, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, address, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockByHash provides a mock function with given fields: ctx, hash, dbTx -func (_m *stateMock) GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*types.Block, error) { - ret := _m.Called(ctx, hash, dbTx) - - var r0 *types.Block - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *types.Block); ok { - r0 = rf(ctx, hash, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Block) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { - r1 = rf(ctx, hash, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockByNumber provides a mock function with given fields: ctx, blockNumber, dbTx -func (_m *stateMock) GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Block, error) { - ret := _m.Called(ctx, blockNumber, dbTx) - - var r0 *types.Block - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *types.Block); ok { - r0 = rf(ctx, blockNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Block) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockHashesSince provides a mock function with given fields: ctx, since, dbTx -func (_m *stateMock) GetL2BlockHashesSince(ctx context.Context, since time.Time, dbTx pgx.Tx) ([]common.Hash, error) { - ret := _m.Called(ctx, since, dbTx) - - var r0 []common.Hash - if rf, ok := ret.Get(0).(func(context.Context, time.Time, pgx.Tx) []common.Hash); ok { - r0 = rf(ctx, since, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Hash) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, time.Time, pgx.Tx) error); ok { - r1 = rf(ctx, since, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockHeaderByNumber provides a mock function with given fields: ctx, blockNumber, dbTx -func (_m *stateMock) GetL2BlockHeaderByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Header, error) { - ret := _m.Called(ctx, blockNumber, dbTx) - - var r0 *types.Header - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *types.Header); ok { - r0 = rf(ctx, blockNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Header) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockTransactionCountByHash provides a mock function with given fields: ctx, hash, dbTx -func (_m *stateMock) GetL2BlockTransactionCountByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(ctx, hash, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) uint64); ok { - r0 = rf(ctx, hash, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { - r1 = rf(ctx, hash, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetL2BlockTransactionCountByNumber provides a mock function with given fields: ctx, blockNumber, dbTx -func (_m *stateMock) GetL2BlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(ctx, blockNumber, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) uint64); ok { - r0 = rf(ctx, blockNumber, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLastConsolidatedL2BlockNumber provides a mock function with given fields: ctx, dbTx -func (_m *stateMock) GetLastConsolidatedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(ctx, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { - r0 = rf(ctx, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLastL2Block provides a mock function with given fields: ctx, dbTx -func (_m *stateMock) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) { - ret := _m.Called(ctx, dbTx) - - var r0 *types.Block - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *types.Block); ok { - r0 = rf(ctx, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Block) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLastL2BlockHeader provides a mock function with given fields: ctx, dbTx -func (_m *stateMock) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) { - ret := _m.Called(ctx, dbTx) - - var r0 *types.Header - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *types.Header); ok { - r0 = rf(ctx, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Header) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLastL2BlockNumber provides a mock function with given fields: ctx, dbTx -func (_m *stateMock) GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(ctx, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { - r0 = rf(ctx, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLogs provides a mock function with given fields: ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx -func (_m *stateMock) GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*types.Log, error) { - ret := _m.Called(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) - - var r0 []*types.Log - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, []common.Address, [][]common.Hash, *common.Hash, *time.Time, pgx.Tx) []*types.Log); ok { - r0 = rf(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*types.Log) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, []common.Address, [][]common.Hash, *common.Hash, *time.Time, pgx.Tx) error); ok { - r1 = rf(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetNonce provides a mock function with given fields: ctx, address, blockNumber, dbTx -func (_m *stateMock) GetNonce(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { - ret := _m.Called(ctx, address, blockNumber, dbTx) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(context.Context, common.Address, uint64, pgx.Tx) uint64); ok { - r0 = rf(ctx, address, blockNumber, dbTx) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Address, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, address, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetStorageAt provides a mock function with given fields: ctx, address, position, blockNumber, dbTx -func (_m *stateMock) GetStorageAt(ctx context.Context, address common.Address, position *big.Int, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) { - ret := _m.Called(ctx, address, position, blockNumber, dbTx) - - var r0 *big.Int - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, uint64, pgx.Tx) *big.Int); ok { - r0 = rf(ctx, address, position, blockNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, address, position, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetSyncingInfo provides a mock function with given fields: ctx, dbTx -func (_m *stateMock) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (state.SyncingInfo, error) { - ret := _m.Called(ctx, dbTx) - - var r0 state.SyncingInfo - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) state.SyncingInfo); ok { - r0 = rf(ctx, dbTx) - } else { - r0 = ret.Get(0).(state.SyncingInfo) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetTransactionByHash provides a mock function with given fields: ctx, transactionHash, dbTx -func (_m *stateMock) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) { - ret := _m.Called(ctx, transactionHash, dbTx) - - var r0 *types.Transaction - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *types.Transaction); ok { - r0 = rf(ctx, transactionHash, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { - r1 = rf(ctx, transactionHash, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetTransactionByL2BlockHashAndIndex provides a mock function with given fields: ctx, blockHash, index, dbTx -func (_m *stateMock) GetTransactionByL2BlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) { - ret := _m.Called(ctx, blockHash, index, dbTx) - - var r0 *types.Transaction - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, uint64, pgx.Tx) *types.Transaction); ok { - r0 = rf(ctx, blockHash, index, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, blockHash, index, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetTransactionByL2BlockNumberAndIndex provides a mock function with given fields: ctx, blockNumber, index, dbTx -func (_m *stateMock) GetTransactionByL2BlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) { - ret := _m.Called(ctx, blockNumber, index, dbTx) - - var r0 *types.Transaction - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) *types.Transaction); ok { - r0 = rf(ctx, blockNumber, index, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, index, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetTransactionReceipt provides a mock function with given fields: ctx, transactionHash, dbTx -func (_m *stateMock) GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Receipt, error) { - ret := _m.Called(ctx, transactionHash, dbTx) - - var r0 *types.Receipt - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *types.Receipt); ok { - r0 = rf(ctx, transactionHash, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Receipt) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { - r1 = rf(ctx, transactionHash, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IsL2BlockConsolidated provides a mock function with given fields: ctx, blockNumber, dbTx -func (_m *stateMock) IsL2BlockConsolidated(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) { - ret := _m.Called(ctx, blockNumber, dbTx) - - var r0 bool - if rf, ok := ret.Get(0).(func(context.Context, int, pgx.Tx) bool); ok { - r0 = rf(ctx, blockNumber, dbTx) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, int, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// IsL2BlockVirtualized provides a mock function with given fields: ctx, blockNumber, dbTx -func (_m *stateMock) IsL2BlockVirtualized(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) { - ret := _m.Called(ctx, blockNumber, dbTx) - - var r0 bool - if rf, ok := ret.Get(0).(func(context.Context, int, pgx.Tx) bool); ok { - r0 = rf(ctx, blockNumber, dbTx) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, int, pgx.Tx) error); ok { - r1 = rf(ctx, blockNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ProcessUnsignedTransaction provides a mock function with given fields: ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx -func (_m *stateMock) ProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) *runtime.ExecutionResult { - ret := _m.Called(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) - - var r0 *runtime.ExecutionResult - if rf, ok := ret.Get(0).(func(context.Context, *types.Transaction, common.Address, *uint64, bool, pgx.Tx) *runtime.ExecutionResult); ok { - r0 = rf(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*runtime.ExecutionResult) - } - } - - return r0 -} - -type mockConstructorTestingTnewStateMock interface { - mock.TestingT - Cleanup(func()) -} - -// newStateMock creates a new instance of stateMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func newStateMock(t mockConstructorTestingTnewStateMock) *stateMock { - mock := &stateMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/jsonrpc/mock_storage.go b/jsonrpc/mock_storage.go new file mode 100644 index 0000000000..105bad5455 --- /dev/null +++ b/jsonrpc/mock_storage.go @@ -0,0 +1,220 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package jsonrpc + +import ( + websocket "github.com/gorilla/websocket" + mock "github.com/stretchr/testify/mock" +) + +// storageMock is an autogenerated mock type for the storageInterface type +type storageMock struct { + mock.Mock +} + +// GetAllBlockFiltersWithWSConn provides a mock function with given fields: +func (_m *storageMock) GetAllBlockFiltersWithWSConn() ([]*Filter, error) { + ret := _m.Called() + + var r0 []*Filter + var r1 error + if rf, ok := ret.Get(0).(func() ([]*Filter, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []*Filter); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*Filter) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAllLogFiltersWithWSConn provides a mock function with given fields: +func (_m *storageMock) GetAllLogFiltersWithWSConn() ([]*Filter, error) { + ret := _m.Called() + + var r0 []*Filter + var r1 error + if rf, ok := ret.Get(0).(func() ([]*Filter, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []*Filter); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*Filter) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetFilter provides a mock function with given fields: filterID +func (_m *storageMock) GetFilter(filterID string) (*Filter, error) { + ret := _m.Called(filterID) + + var r0 *Filter + var r1 error + if rf, ok := ret.Get(0).(func(string) (*Filter, error)); ok { + return rf(filterID) + } + if rf, ok := ret.Get(0).(func(string) *Filter); ok { + r0 = rf(filterID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*Filter) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(filterID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewBlockFilter provides a mock function with given fields: wsConn +func (_m *storageMock) NewBlockFilter(wsConn *websocket.Conn) (string, error) { + ret := _m.Called(wsConn) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(*websocket.Conn) (string, error)); ok { + return rf(wsConn) + } + if rf, ok := ret.Get(0).(func(*websocket.Conn) string); ok { + r0 = rf(wsConn) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(*websocket.Conn) error); ok { + r1 = rf(wsConn) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewLogFilter provides a mock function with given fields: wsConn, filter +func (_m *storageMock) NewLogFilter(wsConn *websocket.Conn, filter LogFilter) (string, error) { + ret := _m.Called(wsConn, filter) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(*websocket.Conn, LogFilter) (string, error)); ok { + return rf(wsConn, filter) + } + if rf, ok := ret.Get(0).(func(*websocket.Conn, LogFilter) string); ok { + r0 = rf(wsConn, filter) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(*websocket.Conn, LogFilter) error); ok { + r1 = rf(wsConn, filter) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewPendingTransactionFilter provides a mock function with given fields: wsConn +func (_m *storageMock) NewPendingTransactionFilter(wsConn *websocket.Conn) (string, error) { + ret := _m.Called(wsConn) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(*websocket.Conn) (string, error)); ok { + return rf(wsConn) + } + if rf, ok := ret.Get(0).(func(*websocket.Conn) string); ok { + r0 = rf(wsConn) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(*websocket.Conn) error); ok { + r1 = rf(wsConn) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UninstallFilter provides a mock function with given fields: filterID +func (_m *storageMock) UninstallFilter(filterID string) error { + ret := _m.Called(filterID) + + var r0 error + if rf, ok := ret.Get(0).(func(string) error); ok { + r0 = rf(filterID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UninstallFilterByWSConn provides a mock function with given fields: wsConn +func (_m *storageMock) UninstallFilterByWSConn(wsConn *websocket.Conn) error { + ret := _m.Called(wsConn) + + var r0 error + if rf, ok := ret.Get(0).(func(*websocket.Conn) error); ok { + r0 = rf(wsConn) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateFilterLastPoll provides a mock function with given fields: filterID +func (_m *storageMock) UpdateFilterLastPoll(filterID string) error { + ret := _m.Called(filterID) + + var r0 error + if rf, ok := ret.Get(0).(func(string) error); ok { + r0 = rf(filterID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTnewStorageMock interface { + mock.TestingT + Cleanup(func()) +} + +// newStorageMock creates a new instance of storageMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newStorageMock(t mockConstructorTestingTnewStorageMock) *storageMock { + mock := &storageMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/jsonrpc/mock_storage_test.go b/jsonrpc/mock_storage_test.go deleted file mode 100644 index 7436a42579..0000000000 --- a/jsonrpc/mock_storage_test.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package jsonrpc - -import mock "github.com/stretchr/testify/mock" - -// storageMock is an autogenerated mock type for the storageInterface type -type storageMock struct { - mock.Mock -} - -// GetFilter provides a mock function with given fields: filterID -func (_m *storageMock) GetFilter(filterID uint64) (*Filter, error) { - ret := _m.Called(filterID) - - var r0 *Filter - if rf, ok := ret.Get(0).(func(uint64) *Filter); ok { - r0 = rf(filterID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*Filter) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(uint64) error); ok { - r1 = rf(filterID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewBlockFilter provides a mock function with given fields: -func (_m *storageMock) NewBlockFilter() (uint64, error) { - ret := _m.Called() - - var r0 uint64 - if rf, ok := ret.Get(0).(func() uint64); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewLogFilter provides a mock function with given fields: filter -func (_m *storageMock) NewLogFilter(filter LogFilter) (uint64, error) { - ret := _m.Called(filter) - - var r0 uint64 - if rf, ok := ret.Get(0).(func(LogFilter) uint64); ok { - r0 = rf(filter) - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(LogFilter) error); ok { - r1 = rf(filter) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewPendingTransactionFilter provides a mock function with given fields: -func (_m *storageMock) NewPendingTransactionFilter() (uint64, error) { - ret := _m.Called() - - var r0 uint64 - if rf, ok := ret.Get(0).(func() uint64); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(uint64) - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UninstallFilter provides a mock function with given fields: filterID -func (_m *storageMock) UninstallFilter(filterID uint64) (bool, error) { - ret := _m.Called(filterID) - - var r0 bool - if rf, ok := ret.Get(0).(func(uint64) bool); ok { - r0 = rf(filterID) - } else { - r0 = ret.Get(0).(bool) - } - - var r1 error - if rf, ok := ret.Get(1).(func(uint64) error); ok { - r1 = rf(filterID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdateFilterLastPoll provides a mock function with given fields: filterID -func (_m *storageMock) UpdateFilterLastPoll(filterID uint64) error { - ret := _m.Called(filterID) - - var r0 error - if rf, ok := ret.Get(0).(func(uint64) error); ok { - r0 = rf(filterID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -type mockConstructorTestingTnewStorageMock interface { - mock.TestingT - Cleanup(func()) -} - -// newStorageMock creates a new instance of storageMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func newStorageMock(t mockConstructorTestingTnewStorageMock) *storageMock { - mock := &storageMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/jsonrpc/mocks/mock_dbtx.go b/jsonrpc/mocks/mock_dbtx.go new file mode 100644 index 0000000000..cfbca16e32 --- /dev/null +++ b/jsonrpc/mocks/mock_dbtx.go @@ -0,0 +1,299 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + pgconn "github.com/jackc/pgconn" + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" +) + +// DBTxMock is an autogenerated mock type for the Tx type +type DBTxMock struct { + mock.Mock +} + +// Begin provides a mock function with given fields: ctx +func (_m *DBTxMock) Begin(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeginFunc provides a mock function with given fields: ctx, f +func (_m *DBTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { + ret := _m.Called(ctx, f) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, func(pgx.Tx) error) error); ok { + r0 = rf(ctx, f) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Commit provides a mock function with given fields: ctx +func (_m *DBTxMock) Commit(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Conn provides a mock function with given fields: +func (_m *DBTxMock) Conn() *pgx.Conn { + ret := _m.Called() + + var r0 *pgx.Conn + if rf, ok := ret.Get(0).(func() *pgx.Conn); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pgx.Conn) + } + } + + return r0 +} + +// CopyFrom provides a mock function with given fields: ctx, tableName, columnNames, rowSrc +func (_m *DBTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { + ret := _m.Called(ctx, tableName, columnNames, rowSrc) + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)); ok { + return rf(ctx, tableName, columnNames, rowSrc) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) int64); ok { + r0 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) error); ok { + r1 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Exec provides a mock function with given fields: ctx, sql, arguments +func (_m *DBTxMock) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, arguments...) + ret := _m.Called(_ca...) + + var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, arguments...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgconn.CommandTag); ok { + r0 = rf(ctx, sql, arguments...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgconn.CommandTag) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(ctx, sql, arguments...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LargeObjects provides a mock function with given fields: +func (_m *DBTxMock) LargeObjects() pgx.LargeObjects { + ret := _m.Called() + + var r0 pgx.LargeObjects + if rf, ok := ret.Get(0).(func() pgx.LargeObjects); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(pgx.LargeObjects) + } + + return r0 +} + +// Prepare provides a mock function with given fields: ctx, name, sql +func (_m *DBTxMock) Prepare(ctx context.Context, name string, sql string) (*pgconn.StatementDescription, error) { + ret := _m.Called(ctx, name, sql) + + var r0 *pgconn.StatementDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*pgconn.StatementDescription, error)); ok { + return rf(ctx, name, sql) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *pgconn.StatementDescription); ok { + r0 = rf(ctx, name, sql) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pgconn.StatementDescription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, name, sql) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Query provides a mock function with given fields: ctx, sql, args +func (_m *DBTxMock) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 pgx.Rows + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgx.Rows, error)); ok { + return rf(ctx, sql, args...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Rows); ok { + r0 = rf(ctx, sql, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Rows) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(ctx, sql, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// QueryFunc provides a mock function with given fields: ctx, sql, args, scans, f +func (_m *DBTxMock) QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error) { + ret := _m.Called(ctx, sql, args, scans, f) + + var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, args, scans, f) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) pgconn.CommandTag); ok { + r0 = rf(ctx, sql, args, scans, f) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgconn.CommandTag) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) error); ok { + r1 = rf(ctx, sql, args, scans, f) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// QueryRow provides a mock function with given fields: ctx, sql, args +func (_m *DBTxMock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 pgx.Row + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Row); ok { + r0 = rf(ctx, sql, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Row) + } + } + + return r0 +} + +// Rollback provides a mock function with given fields: ctx +func (_m *DBTxMock) Rollback(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SendBatch provides a mock function with given fields: ctx, b +func (_m *DBTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { + ret := _m.Called(ctx, b) + + var r0 pgx.BatchResults + if rf, ok := ret.Get(0).(func(context.Context, *pgx.Batch) pgx.BatchResults); ok { + r0 = rf(ctx, b) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.BatchResults) + } + } + + return r0 +} + +type mockConstructorTestingTNewDBTxMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewDBTxMock creates a new instance of DBTxMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewDBTxMock(t mockConstructorTestingTNewDBTxMock) *DBTxMock { + mock := &DBTxMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/jsonrpc/mock_pool_test.go b/jsonrpc/mocks/mock_pool.go similarity index 62% rename from jsonrpc/mock_pool_test.go rename to jsonrpc/mocks/mock_pool.go index 845d7df52a..84e3111f6b 100644 --- a/jsonrpc/mock_pool_test.go +++ b/jsonrpc/mocks/mock_pool.go @@ -1,6 +1,6 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. -package jsonrpc +package mocks import ( context "context" @@ -16,18 +16,18 @@ import ( types "github.com/ethereum/go-ethereum/core/types" ) -// poolMock is an autogenerated mock type for the jsonRPCTxPool type -type poolMock struct { +// PoolMock is an autogenerated mock type for the PoolInterface type +type PoolMock struct { mock.Mock } -// AddTx provides a mock function with given fields: ctx, tx -func (_m *poolMock) AddTx(ctx context.Context, tx types.Transaction) error { - ret := _m.Called(ctx, tx) +// AddTx provides a mock function with given fields: ctx, tx, ip +func (_m *PoolMock) AddTx(ctx context.Context, tx types.Transaction, ip string) error { + ret := _m.Called(ctx, tx, ip) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.Transaction) error); ok { - r0 = rf(ctx, tx) + if rf, ok := ret.Get(0).(func(context.Context, types.Transaction, string) error); ok { + r0 = rf(ctx, tx, ip) } else { r0 = ret.Error(0) } @@ -36,17 +36,20 @@ func (_m *poolMock) AddTx(ctx context.Context, tx types.Transaction) error { } // CountPendingTransactions provides a mock function with given fields: ctx -func (_m *poolMock) CountPendingTransactions(ctx context.Context) (uint64, error) { +func (_m *PoolMock) CountPendingTransactions(ctx context.Context) (uint64, error) { ret := _m.Called(ctx) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { r0 = rf(ctx) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -57,17 +60,20 @@ func (_m *poolMock) CountPendingTransactions(ctx context.Context) (uint64, error } // GetGasPrice provides a mock function with given fields: ctx -func (_m *poolMock) GetGasPrice(ctx context.Context) (uint64, error) { +func (_m *PoolMock) GetGasPrice(ctx context.Context) (uint64, error) { ret := _m.Called(ctx) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { r0 = rf(ctx) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -78,17 +84,20 @@ func (_m *poolMock) GetGasPrice(ctx context.Context) (uint64, error) { } // GetNonce provides a mock function with given fields: ctx, address -func (_m *poolMock) GetNonce(ctx context.Context, address common.Address) (uint64, error) { +func (_m *PoolMock) GetNonce(ctx context.Context, address common.Address) (uint64, error) { ret := _m.Called(ctx, address) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address) (uint64, error)); ok { + return rf(ctx, address) + } if rf, ok := ret.Get(0).(func(context.Context, common.Address) uint64); ok { r0 = rf(ctx, address) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, common.Address) error); ok { r1 = rf(ctx, address) } else { @@ -99,10 +108,14 @@ func (_m *poolMock) GetNonce(ctx context.Context, address common.Address) (uint6 } // GetPendingTxHashesSince provides a mock function with given fields: ctx, since -func (_m *poolMock) GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) { +func (_m *PoolMock) GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) { ret := _m.Called(ctx, since) var r0 []common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time) ([]common.Hash, error)); ok { + return rf(ctx, since) + } if rf, ok := ret.Get(0).(func(context.Context, time.Time) []common.Hash); ok { r0 = rf(ctx, since) } else { @@ -111,7 +124,6 @@ func (_m *poolMock) GetPendingTxHashesSince(ctx context.Context, since time.Time } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, time.Time) error); ok { r1 = rf(ctx, since) } else { @@ -121,22 +133,25 @@ func (_m *poolMock) GetPendingTxHashesSince(ctx context.Context, since time.Time return r0, r1 } -// GetPendingTxs provides a mock function with given fields: ctx, isClaims, limit -func (_m *poolMock) GetPendingTxs(ctx context.Context, isClaims bool, limit uint64) ([]pool.Transaction, error) { - ret := _m.Called(ctx, isClaims, limit) +// GetPendingTxs provides a mock function with given fields: ctx, limit +func (_m *PoolMock) GetPendingTxs(ctx context.Context, limit uint64) ([]pool.Transaction, error) { + ret := _m.Called(ctx, limit) var r0 []pool.Transaction - if rf, ok := ret.Get(0).(func(context.Context, bool, uint64) []pool.Transaction); ok { - r0 = rf(ctx, isClaims, limit) + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]pool.Transaction, error)); ok { + return rf(ctx, limit) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []pool.Transaction); ok { + r0 = rf(ctx, limit) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]pool.Transaction) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, bool, uint64) error); ok { - r1 = rf(ctx, isClaims, limit) + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, limit) } else { r1 = ret.Error(1) } @@ -145,10 +160,14 @@ func (_m *poolMock) GetPendingTxs(ctx context.Context, isClaims bool, limit uint } // GetTxByHash provides a mock function with given fields: ctx, hash -func (_m *poolMock) GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Transaction, error) { +func (_m *PoolMock) GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Transaction, error) { ret := _m.Called(ctx, hash) var r0 *pool.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*pool.Transaction, error)); ok { + return rf(ctx, hash) + } if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *pool.Transaction); ok { r0 = rf(ctx, hash) } else { @@ -157,7 +176,6 @@ func (_m *poolMock) GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Tr } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { r1 = rf(ctx, hash) } else { @@ -167,14 +185,14 @@ func (_m *poolMock) GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Tr return r0, r1 } -type mockConstructorTestingTnewPoolMock interface { +type mockConstructorTestingTNewPoolMock interface { mock.TestingT Cleanup(func()) } -// newPoolMock creates a new instance of poolMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func newPoolMock(t mockConstructorTestingTnewPoolMock) *poolMock { - mock := &poolMock{} +// NewPoolMock creates a new instance of PoolMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewPoolMock(t mockConstructorTestingTNewPoolMock) *PoolMock { + mock := &PoolMock{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/jsonrpc/mocks/mock_state.go b/jsonrpc/mocks/mock_state.go new file mode 100644 index 0000000000..960abe17c7 --- /dev/null +++ b/jsonrpc/mocks/mock_state.go @@ -0,0 +1,945 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + coretypes "github.com/ethereum/go-ethereum/core/types" + + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" + + runtime "github.com/0xPolygonHermez/zkevm-node/state/runtime" + + state "github.com/0xPolygonHermez/zkevm-node/state" + + time "time" +) + +// StateMock is an autogenerated mock type for the StateInterface type +type StateMock struct { + mock.Mock +} + +// BatchNumberByL2BlockNumber provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) BatchNumberByL2BlockNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (uint64, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) uint64); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeginStateTransaction provides a mock function with given fields: ctx +func (_m *StateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DebugTransaction provides a mock function with given fields: ctx, transactionHash, traceConfig, dbTx +func (_m *StateMock) DebugTransaction(ctx context.Context, transactionHash common.Hash, traceConfig state.TraceConfig, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { + ret := _m.Called(ctx, transactionHash, traceConfig, dbTx) + + var r0 *runtime.ExecutionResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, state.TraceConfig, pgx.Tx) (*runtime.ExecutionResult, error)); ok { + return rf(ctx, transactionHash, traceConfig, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, state.TraceConfig, pgx.Tx) *runtime.ExecutionResult); ok { + r0 = rf(ctx, transactionHash, traceConfig, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.ExecutionResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, state.TraceConfig, pgx.Tx) error); ok { + r1 = rf(ctx, transactionHash, traceConfig, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EstimateGas provides a mock function with given fields: transaction, senderAddress, l2BlockNumber, dbTx +func (_m *StateMock) EstimateGas(transaction *coretypes.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error) { + ret := _m.Called(transaction, senderAddress, l2BlockNumber, dbTx) + + var r0 uint64 + var r1 []byte + var r2 error + if rf, ok := ret.Get(0).(func(*coretypes.Transaction, common.Address, *uint64, pgx.Tx) (uint64, []byte, error)); ok { + return rf(transaction, senderAddress, l2BlockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(*coretypes.Transaction, common.Address, *uint64, pgx.Tx) uint64); ok { + r0 = rf(transaction, senderAddress, l2BlockNumber, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(*coretypes.Transaction, common.Address, *uint64, pgx.Tx) []byte); ok { + r1 = rf(transaction, senderAddress, l2BlockNumber, dbTx) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]byte) + } + } + + if rf, ok := ret.Get(2).(func(*coretypes.Transaction, common.Address, *uint64, pgx.Tx) error); ok { + r2 = rf(transaction, senderAddress, l2BlockNumber, dbTx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetBalance provides a mock function with given fields: ctx, address, root +func (_m *StateMock) GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + ret := _m.Called(ctx, address, root) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) (*big.Int, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) *big.Int); ok { + r0 = rf(ctx, address, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetCode provides a mock function with given fields: ctx, address, root +func (_m *StateMock) GetCode(ctx context.Context, address common.Address, root common.Hash) ([]byte, error) { + ret := _m.Called(ctx, address, root) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) ([]byte, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) []byte); ok { + r0 = rf(ctx, address, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetExitRootByGlobalExitRoot provides a mock function with given fields: ctx, ger, dbTx +func (_m *StateMock) GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*state.GlobalExitRoot, error) { + ret := _m.Called(ctx, ger, dbTx) + + var r0 *state.GlobalExitRoot + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*state.GlobalExitRoot, error)); ok { + return rf(ctx, ger, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *state.GlobalExitRoot); ok { + r0 = rf(ctx, ger, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.GlobalExitRoot) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { + r1 = rf(ctx, ger, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockByHash provides a mock function with given fields: ctx, hash, dbTx +func (_m *StateMock) GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*coretypes.Block, error) { + ret := _m.Called(ctx, hash, dbTx) + + var r0 *coretypes.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*coretypes.Block, error)); ok { + return rf(ctx, hash, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *coretypes.Block); ok { + r0 = rf(ctx, hash, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { + r1 = rf(ctx, hash, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockByNumber provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*coretypes.Block, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 *coretypes.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*coretypes.Block, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *coretypes.Block); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockHashesSince provides a mock function with given fields: ctx, since, dbTx +func (_m *StateMock) GetL2BlockHashesSince(ctx context.Context, since time.Time, dbTx pgx.Tx) ([]common.Hash, error) { + ret := _m.Called(ctx, since, dbTx) + + var r0 []common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time, pgx.Tx) ([]common.Hash, error)); ok { + return rf(ctx, since, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, time.Time, pgx.Tx) []common.Hash); ok { + r0 = rf(ctx, since, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Hash) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, time.Time, pgx.Tx) error); ok { + r1 = rf(ctx, since, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockHeaderByNumber provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) GetL2BlockHeaderByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*coretypes.Header, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 *coretypes.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*coretypes.Header, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *coretypes.Header); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Header) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockTransactionCountByHash provides a mock function with given fields: ctx, hash, dbTx +func (_m *StateMock) GetL2BlockTransactionCountByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, hash, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (uint64, error)); ok { + return rf(ctx, hash, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) uint64); ok { + r0 = rf(ctx, hash, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { + r1 = rf(ctx, hash, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetL2BlockTransactionCountByNumber provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) GetL2BlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (uint64, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) uint64); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBatchNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastConsolidatedL2BlockNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastConsolidatedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastL2Block provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*coretypes.Block, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *coretypes.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*coretypes.Block, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *coretypes.Block); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastL2BlockNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVerifiedBatch provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.VerifiedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.VerifiedBatch, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.VerifiedBatch); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.VerifiedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVirtualBatchNum provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVirtualizedL2BlockNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastVirtualizedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogs provides a mock function with given fields: ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx +func (_m *StateMock) GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*coretypes.Log, error) { + ret := _m.Called(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) + + var r0 []*coretypes.Log + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, []common.Address, [][]common.Hash, *common.Hash, *time.Time, pgx.Tx) ([]*coretypes.Log, error)); ok { + return rf(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, []common.Address, [][]common.Hash, *common.Hash, *time.Time, pgx.Tx) []*coretypes.Log); ok { + r0 = rf(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*coretypes.Log) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, []common.Address, [][]common.Hash, *common.Hash, *time.Time, pgx.Tx) error); ok { + r1 = rf(ctx, fromBlock, toBlock, addresses, topics, blockHash, since, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetNonce provides a mock function with given fields: ctx, address, root +func (_m *StateMock) GetNonce(ctx context.Context, address common.Address, root common.Hash) (uint64, error) { + ret := _m.Called(ctx, address, root) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) (uint64, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) uint64); ok { + r0 = rf(ctx, address, root) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetStorageAt provides a mock function with given fields: ctx, address, position, root +func (_m *StateMock) GetStorageAt(ctx context.Context, address common.Address, position *big.Int, root common.Hash) (*big.Int, error) { + ret := _m.Called(ctx, address, position, root) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, common.Hash) (*big.Int, error)); ok { + return rf(ctx, address, position, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, common.Hash) *big.Int); ok { + r0 = rf(ctx, address, position, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int, common.Hash) error); ok { + r1 = rf(ctx, address, position, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetSyncingInfo provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (state.SyncingInfo, error) { + ret := _m.Called(ctx, dbTx) + + var r0 state.SyncingInfo + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (state.SyncingInfo, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) state.SyncingInfo); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(state.SyncingInfo) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionByHash provides a mock function with given fields: ctx, transactionHash, dbTx +func (_m *StateMock) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*coretypes.Transaction, error) { + ret := _m.Called(ctx, transactionHash, dbTx) + + var r0 *coretypes.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*coretypes.Transaction, error)); ok { + return rf(ctx, transactionHash, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *coretypes.Transaction); ok { + r0 = rf(ctx, transactionHash, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { + r1 = rf(ctx, transactionHash, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionByL2BlockHashAndIndex provides a mock function with given fields: ctx, blockHash, index, dbTx +func (_m *StateMock) GetTransactionByL2BlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*coretypes.Transaction, error) { + ret := _m.Called(ctx, blockHash, index, dbTx) + + var r0 *coretypes.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, uint64, pgx.Tx) (*coretypes.Transaction, error)); ok { + return rf(ctx, blockHash, index, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, uint64, pgx.Tx) *coretypes.Transaction); ok { + r0 = rf(ctx, blockHash, index, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockHash, index, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionByL2BlockNumberAndIndex provides a mock function with given fields: ctx, blockNumber, index, dbTx +func (_m *StateMock) GetTransactionByL2BlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*coretypes.Transaction, error) { + ret := _m.Called(ctx, blockNumber, index, dbTx) + + var r0 *coretypes.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) (*coretypes.Transaction, error)); ok { + return rf(ctx, blockNumber, index, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) *coretypes.Transaction); ok { + r0 = rf(ctx, blockNumber, index, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, index, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionReceipt provides a mock function with given fields: ctx, transactionHash, dbTx +func (_m *StateMock) GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*coretypes.Receipt, error) { + ret := _m.Called(ctx, transactionHash, dbTx) + + var r0 *coretypes.Receipt + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) (*coretypes.Receipt, error)); ok { + return rf(ctx, transactionHash, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *coretypes.Receipt); ok { + r0 = rf(ctx, transactionHash, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.Receipt) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { + r1 = rf(ctx, transactionHash, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionsByBatchNumber provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]coretypes.Transaction, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 []coretypes.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) ([]coretypes.Transaction, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) []coretypes.Transaction); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]coretypes.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetVerifiedBatch provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetVerifiedBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.VerifiedBatch, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 *state.VerifiedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.VerifiedBatch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.VerifiedBatch); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.VerifiedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetVirtualBatch provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetVirtualBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.VirtualBatch, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 *state.VirtualBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.VirtualBatch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.VirtualBatch); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.VirtualBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IsL2BlockConsolidated provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) IsL2BlockConsolidated(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (bool, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) bool); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IsL2BlockVirtualized provides a mock function with given fields: ctx, blockNumber, dbTx +func (_m *StateMock) IsL2BlockVirtualized(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) { + ret := _m.Called(ctx, blockNumber, dbTx) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (bool, error)); ok { + return rf(ctx, blockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) bool); ok { + r0 = rf(ctx, blockNumber, dbTx) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, blockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PrepareWebSocket provides a mock function with given fields: +func (_m *StateMock) PrepareWebSocket() { + _m.Called() +} + +// ProcessUnsignedTransaction provides a mock function with given fields: ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx +func (_m *StateMock) ProcessUnsignedTransaction(ctx context.Context, tx *coretypes.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { + ret := _m.Called(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) + + var r0 *runtime.ExecutionResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *coretypes.Transaction, common.Address, *uint64, bool, pgx.Tx) (*runtime.ExecutionResult, error)); ok { + return rf(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, *coretypes.Transaction, common.Address, *uint64, bool, pgx.Tx) *runtime.ExecutionResult); ok { + r0 = rf(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*runtime.ExecutionResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *coretypes.Transaction, common.Address, *uint64, bool, pgx.Tx) error); ok { + r1 = rf(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RegisterNewL2BlockEventHandler provides a mock function with given fields: h +func (_m *StateMock) RegisterNewL2BlockEventHandler(h state.NewL2BlockEventHandler) { + _m.Called(h) +} + +type mockConstructorTestingTNewStateMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewStateMock creates a new instance of StateMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewStateMock(t mockConstructorTestingTNewStateMock) *StateMock { + mock := &StateMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/jsonrpc/net.go b/jsonrpc/net.go deleted file mode 100644 index 4b6db0b90e..0000000000 --- a/jsonrpc/net.go +++ /dev/null @@ -1,17 +0,0 @@ -package jsonrpc - -import ( - "strconv" - - "github.com/0xPolygonHermez/zkevm-node/encoding" -) - -// Net contains implementations for the "net" RPC endpoints -type Net struct { - cfg Config -} - -// Version returns the current network id -func (n *Net) Version() (interface{}, rpcError) { - return strconv.FormatUint(n.cfg.ChainID, encoding.Base10), nil -} diff --git a/jsonrpc/pgstorage.go b/jsonrpc/pgstorage.go deleted file mode 100644 index b71eb5ef2f..0000000000 --- a/jsonrpc/pgstorage.go +++ /dev/null @@ -1,121 +0,0 @@ -package jsonrpc - -import ( - "context" - "encoding/json" - "errors" - "time" - - "github.com/0xPolygonHermez/zkevm-node/db" - "github.com/jackc/pgx/v4" - "github.com/jackc/pgx/v4/pgxpool" -) - -const ( - // FilterTypeLog represents a filter of type log. - FilterTypeLog = "log" - // FilterTypeBlock represents a filter of type block. - FilterTypeBlock = "block" - // FilterTypePendingTx represent a filter of type pending Tx. - FilterTypePendingTx = "pendingTx" -) - -// ErrNotFound represent a not found error. -var ErrNotFound = errors.New("object not found") - -// PostgresStorage uses a postgres database to store the data -// related to the json rpc server -type PostgresStorage struct { - db *pgxpool.Pool -} - -// NewPostgresStorage creates and initializes an instance of PostgresStorage -func NewPostgresStorage(cfg db.Config) (*PostgresStorage, error) { - poolDB, err := db.NewSQLDB(cfg) - if err != nil { - return nil, err - } - - return &PostgresStorage{ - db: poolDB, - }, nil -} - -// NewLogFilter persists a new log filter -func (s *PostgresStorage) NewLogFilter(filter LogFilter) (uint64, error) { - parametersBytes, err := json.Marshal(&filter) - if err != nil { - return 0, err - } - - parameters := string(parametersBytes) - - return s.insertFilter(Filter{ - Type: FilterTypeLog, - Parameters: parameters, - }) -} - -// NewBlockFilter persists a new block log filter -func (s *PostgresStorage) NewBlockFilter() (uint64, error) { - return s.insertFilter(Filter{ - Type: FilterTypeBlock, - Parameters: "{}", - }) -} - -// NewPendingTransactionFilter persists a new pending transaction filter -func (s *PostgresStorage) NewPendingTransactionFilter() (uint64, error) { - return s.insertFilter(Filter{ - Type: FilterTypePendingTx, - Parameters: "{}", - }) -} - -// insertFilter persists the filter to the db -func (s *PostgresStorage) insertFilter(filter Filter) (uint64, error) { - lastPoll := time.Now().UTC() - sql := `INSERT INTO rpc.filters (filter_type, parameters, last_poll) VALUES($1, $2, $3) RETURNING "id"` - - var id uint64 - err := s.db.QueryRow(context.Background(), sql, filter.Type, filter.Parameters, lastPoll).Scan(&id) - if err != nil { - return 0, err - } - - return id, nil -} - -// GetFilter gets a filter by its id -func (s *PostgresStorage) GetFilter(filterID uint64) (*Filter, error) { - filter := &Filter{} - sql := `SELECT id, filter_type, parameters, last_poll FROM rpc.filters WHERE id = $1` - err := s.db.QueryRow(context.Background(), sql, filterID).Scan(&filter.ID, &filter.Type, &filter.Parameters, &filter.LastPoll) - if errors.Is(err, pgx.ErrNoRows) { - return nil, ErrNotFound - } else if err != nil { - return nil, err - } - - return filter, nil -} - -// UpdateFilterLastPoll updates the last poll to now -func (s *PostgresStorage) UpdateFilterLastPoll(filterID uint64) error { - sql := "UPDATE rpc.filters SET last_poll = $2 WHERE id = $1" - _, err := s.db.Exec(context.Background(), sql, filterID, time.Now().UTC()) - if err != nil { - return err - } - return nil -} - -// UninstallFilter deletes a filter by its id -func (s *PostgresStorage) UninstallFilter(filterID uint64) (bool, error) { - sql := "DELETE FROM rpc.filters WHERE id = $1" - res, err := s.db.Exec(context.Background(), sql, filterID) - if err != nil { - return false, err - } - return res.RowsAffected() > 0, nil -} diff --git a/jsonrpc/query.go b/jsonrpc/query.go index 30e0eeeb96..2cc375dd36 100644 --- a/jsonrpc/query.go +++ b/jsonrpc/query.go @@ -6,32 +6,37 @@ import ( "time" "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + "github.com/gorilla/websocket" +) + +const ( + // FilterTypeLog represents a filter of type log. + FilterTypeLog = "log" + // FilterTypeBlock represents a filter of type block. + FilterTypeBlock = "block" + // FilterTypePendingTx represent a filter of type pending Tx. + FilterTypePendingTx = "pendingTx" ) // Filter represents a filter. type Filter struct { - ID uint64 - Type string - Parameters string + ID string + Type FilterType + Parameters interface{} LastPoll time.Time + WsConn *websocket.Conn } -// LogFilterRequest represents a log filter request. -type LogFilterRequest struct { - BlockHash *common.Hash `json:"blockHash,omitempty"` - FromBlock string `json:"fromBlock,omitempty"` - ToBlock string `json:"toBlock,omitempty"` - Address interface{} `json:"address,omitempty"` - Topics []interface{} `json:"topics,omitempty"` -} +// FilterType express the type of the filter, block, logs, pending transactions +type FilterType string // LogFilter is a filter for logs type LogFilter struct { BlockHash *common.Hash - FromBlock BlockNumber - ToBlock BlockNumber + FromBlock *types.BlockNumber + ToBlock *types.BlockNumber Addresses []common.Address Topics [][]common.Hash Since *time.Time @@ -78,20 +83,24 @@ func (f *LogFilter) addAddress(raw string) error { // MarshalJSON allows to customize the JSON representation. func (f *LogFilter) MarshalJSON() ([]byte, error) { - var obj LogFilterRequest + var obj types.LogFilterRequest obj.BlockHash = f.BlockHash - if f.FromBlock == LatestBlockNumber { - obj.FromBlock = "" - } else { - obj.FromBlock = hex.EncodeUint64(uint64(f.FromBlock)) + if f.FromBlock != nil && (*f.FromBlock == types.LatestBlockNumber) { + fromblock := "" + obj.FromBlock = &fromblock + } else if f.FromBlock != nil { + fromblock := hex.EncodeUint64(uint64(*f.FromBlock)) + obj.FromBlock = &fromblock } - if f.ToBlock == LatestBlockNumber { - obj.ToBlock = "" - } else { - obj.ToBlock = hex.EncodeUint64(uint64(f.ToBlock)) + if f.ToBlock != nil && (*f.ToBlock == types.LatestBlockNumber) { + toblock := "" + obj.ToBlock = &toblock + } else if f.ToBlock != nil { + toblock := hex.EncodeUint64(uint64(*f.ToBlock)) + obj.ToBlock = &toblock } if f.Addresses != nil { @@ -118,7 +127,7 @@ func (f *LogFilter) MarshalJSON() ([]byte, error) { // UnmarshalJSON decodes a json object func (f *LogFilter) UnmarshalJSON(data []byte) error { - var obj LogFilterRequest + var obj types.LogFilterRequest err := json.Unmarshal(data, &obj) @@ -127,21 +136,26 @@ func (f *LogFilter) UnmarshalJSON(data []byte) error { } f.BlockHash = obj.BlockHash + lbb := types.LatestBlockNumber - if obj.FromBlock == "" { - f.FromBlock = LatestBlockNumber - } else { - if f.FromBlock, err = stringToBlockNumber(obj.FromBlock); err != nil { + if obj.FromBlock != nil && *obj.FromBlock == "" { + f.FromBlock = &lbb + } else if obj.FromBlock != nil { + bn, err := types.StringToBlockNumber(*obj.FromBlock) + if err != nil { return err } + f.FromBlock = &bn } - if obj.ToBlock == "" { - f.ToBlock = LatestBlockNumber - } else { - if f.ToBlock, err = stringToBlockNumber(obj.ToBlock); err != nil { + if obj.ToBlock != nil && *obj.ToBlock == "" { + f.ToBlock = &lbb + } else if obj.ToBlock != nil { + bn, err := types.StringToBlockNumber(*obj.ToBlock) + if err != nil { return err } + f.ToBlock = &bn } if obj.Address != nil { diff --git a/jsonrpc/server.go b/jsonrpc/server.go index 6670acf652..433bbfed8d 100644 --- a/jsonrpc/server.go +++ b/jsonrpc/server.go @@ -6,12 +6,16 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net" "net/http" + "time" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/metrics" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/didip/tollbooth/v6" + "github.com/gorilla/websocket" ) const ( @@ -27,65 +31,88 @@ const ( APITxPool = "txpool" // APIWeb3 represents the web3 API prefix. APIWeb3 = "web3" + + wsBufferSizeLimitInBytes = 1024 ) // Server is an API backend to handle RPC requests type Server struct { - config Config - handler *Handler - srv *http.Server + config Config + chainID uint64 + handler *Handler + srv *http.Server + wsSrv *http.Server + wsUpgrader websocket.Upgrader } // NewServer returns the JsonRPC server -func NewServer(cfg Config, p jsonRPCTxPool, s stateInterface, - gpe gasPriceEstimator, storage storageInterface, apis map[string]bool) *Server { +func NewServer( + cfg Config, + chainID uint64, + p types.PoolInterface, + s types.StateInterface, + storage storageInterface, + apis map[string]bool, +) *Server { + s.PrepareWebSocket() handler := newJSONRpcHandler() if _, ok := apis[APIEth]; ok { - ethEndpoints := &Eth{cfg: cfg, pool: p, state: s, gpe: gpe, storage: storage} + ethEndpoints := newEthEndpoints(cfg, chainID, p, s, storage) handler.registerService(APIEth, ethEndpoints) } if _, ok := apis[APINet]; ok { - netEndpoints := &Net{cfg: cfg} + netEndpoints := &NetEndpoints{cfg: cfg, chainID: chainID} handler.registerService(APINet, netEndpoints) } if _, ok := apis[APIZKEVM]; ok { - hezEndpoints := &ZKEVM{state: s, config: cfg} - handler.registerService(APIZKEVM, hezEndpoints) + zkEVMEndpoints := &ZKEVMEndpoints{state: s, config: cfg} + handler.registerService(APIZKEVM, zkEVMEndpoints) } if _, ok := apis[APITxPool]; ok { - txPoolEndpoints := &TxPool{} + txPoolEndpoints := &TxPoolEndpoints{} handler.registerService(APITxPool, txPoolEndpoints) } if _, ok := apis[APIDebug]; ok { - debugEndpoints := &Debug{state: s} + debugEndpoints := &DebugEndpoints{state: s} handler.registerService(APIDebug, debugEndpoints) } if _, ok := apis[APIWeb3]; ok { - web3Endpoints := &Web3{} + web3Endpoints := &Web3Endpoints{} handler.registerService(APIWeb3, web3Endpoints) } srv := &Server{ config: cfg, handler: handler, + chainID: chainID, } return srv } // Start initializes the JSON RPC server to listen for request func (s *Server) Start() error { + metrics.Register() + + if s.config.WebSockets.Enabled { + go s.startWS() + } + + return s.startHTTP() +} + +// startHTTP starts a server to respond http requests +func (s *Server) startHTTP() error { if s.srv != nil { return fmt.Errorf("server already started") } address := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port) - log.Infof("http server started: %s", address) lis, err := net.Listen("tcp", address) if err != nil { @@ -99,8 +126,12 @@ func (s *Server) Start() error { mux.Handle("/", tollbooth.LimitFuncHandler(lmt, s.handle)) s.srv = &http.Server{ - Handler: mux, + Handler: mux, + ReadHeaderTimeout: s.config.ReadTimeout.Duration, + ReadTimeout: s.config.ReadTimeout.Duration, + WriteTimeout: s.config.WriteTimeout.Duration, } + log.Infof("http server started: %s", address) if err := s.srv.Serve(lis); err != nil { if err == http.ErrServerClosed { log.Infof("http server stopped") @@ -112,21 +143,70 @@ func (s *Server) Start() error { return nil } -// Stop shutdown the rpc server -func (s *Server) Stop() error { - if s.srv == nil { - return nil +// startWS starts a server to respond WebSockets connections +func (s *Server) startWS() { + log.Infof("starting websocket server") + + if s.wsSrv != nil { + log.Errorf("websocket server already started") + return } - if err := s.srv.Shutdown(context.Background()); err != nil { - return err + address := fmt.Sprintf("%s:%d", s.config.WebSockets.Host, s.config.WebSockets.Port) + + lis, err := net.Listen("tcp", address) + if err != nil { + log.Errorf("failed to create tcp listener: %v", err) + return } - if err := s.srv.Close(); err != nil { - return err + mux := http.NewServeMux() + mux.HandleFunc("/", s.handleWs) + + s.wsSrv = &http.Server{ + Handler: mux, + ReadHeaderTimeout: s.config.ReadTimeout.Duration, + ReadTimeout: s.config.ReadTimeout.Duration, + WriteTimeout: s.config.WriteTimeout.Duration, + } + s.wsUpgrader = websocket.Upgrader{ + ReadBufferSize: wsBufferSizeLimitInBytes, + WriteBufferSize: wsBufferSizeLimitInBytes, + } + log.Infof("websocket server started: %s", address) + if err := s.wsSrv.Serve(lis); err != nil { + if err == http.ErrServerClosed { + log.Infof("websocket server stopped") + return + } + log.Errorf("closed websocket connection: %v", err) + return + } +} + +// Stop shutdown the rpc server +func (s *Server) Stop() error { + if s.srv != nil { + if err := s.srv.Shutdown(context.Background()); err != nil { + return err + } + + if err := s.srv.Close(); err != nil { + return err + } + s.srv = nil } - s.srv = nil + if s.wsSrv != nil { + if err := s.wsSrv.Shutdown(context.Background()); err != nil { + return err + } + + if err := s.wsSrv.Close(); err != nil { + return err + } + s.wsSrv = nil + } return nil } @@ -138,10 +218,12 @@ func (s *Server) handle(w http.ResponseWriter, req *http.Request) { w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") if (*req).Method == "OPTIONS" { + // TODO(pg): need to count it in the metrics? return } if req.Method == "GET" { + // TODO(pg): need to count it in the metrics? _, err := w.Write([]byte("zkEVM JSON RPC Server")) if err != nil { log.Error(err) @@ -151,72 +233,80 @@ func (s *Server) handle(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { err := errors.New("method " + req.Method + " not allowed") - handleError(w, err) + s.handleInvalidRequest(w, err) return } - data, err := ioutil.ReadAll(req.Body) + data, err := io.ReadAll(req.Body) if err != nil { - handleError(w, err) + s.handleInvalidRequest(w, err) return } single, err := s.isSingleRequest(data) if err != nil { - handleError(w, err) + s.handleInvalidRequest(w, err) return } + start := time.Now() + var respLen int if single { - s.handleSingleRequest(w, data) + respLen = s.handleSingleRequest(req, w, data) } else { - s.handleBatchRequest(w, data) + respLen = s.handleBatchRequest(req, w, data) } + metrics.RequestDuration(start) + combinedLog(req, start, http.StatusOK, respLen) } -func (s *Server) isSingleRequest(data []byte) (bool, rpcError) { +func (s *Server) isSingleRequest(data []byte) (bool, types.Error) { x := bytes.TrimLeft(data, " \t\r\n") if len(x) == 0 { - return false, newRPCError(invalidRequestErrorCode, "Invalid json request") + return false, types.NewRPCError(types.InvalidRequestErrorCode, "Invalid json request") } return x[0] == '{', nil } -func (s *Server) handleSingleRequest(w http.ResponseWriter, data []byte) { +func (s *Server) handleSingleRequest(httpRequest *http.Request, w http.ResponseWriter, data []byte) int { + defer metrics.RequestHandled(metrics.RequestHandledLabelSingle) request, err := s.parseRequest(data) if err != nil { handleError(w, err) - return + return 0 } - - response := s.handler.Handle(request) + req := handleRequest{Request: request, HttpRequest: httpRequest} + response := s.handler.Handle(req) respBytes, err := json.Marshal(response) if err != nil { handleError(w, err) - return + return 0 } _, err = w.Write(respBytes) if err != nil { handleError(w, err) - return + return 0 } + return len(respBytes) } -func (s *Server) handleBatchRequest(w http.ResponseWriter, data []byte) { +func (s *Server) handleBatchRequest(httpRequest *http.Request, w http.ResponseWriter, data []byte) int { + defer metrics.RequestHandled(metrics.RequestHandledLabelBatch) requests, err := s.parseRequests(data) if err != nil { handleError(w, err) - return + return 0 } - responses := make([]Response, 0, len(requests)) + responses := make([]types.Response, 0, len(requests)) for _, request := range requests { - response := s.handler.Handle(request) + req := handleRequest{Request: request, HttpRequest: httpRequest} + response := s.handler.Handle(req) responses = append(responses, response) } @@ -224,29 +314,86 @@ func (s *Server) handleBatchRequest(w http.ResponseWriter, data []byte) { _, err = w.Write(respBytes) if err != nil { log.Error(err) + return 0 } + return len(respBytes) } -func (s *Server) parseRequest(data []byte) (Request, error) { - var req Request +func (s *Server) parseRequest(data []byte) (types.Request, error) { + var req types.Request if err := json.Unmarshal(data, &req); err != nil { - return Request{}, newRPCError(invalidRequestErrorCode, "Invalid json request") + return types.Request{}, types.NewRPCError(types.InvalidRequestErrorCode, "Invalid json request") } return req, nil } -func (s *Server) parseRequests(data []byte) ([]Request, error) { - var requests []Request +func (s *Server) parseRequests(data []byte) ([]types.Request, error) { + var requests []types.Request if err := json.Unmarshal(data, &requests); err != nil { - return nil, newRPCError(invalidRequestErrorCode, "Invalid json request") + return nil, types.NewRPCError(types.InvalidRequestErrorCode, "Invalid json request") } return requests, nil } +func (s *Server) handleInvalidRequest(w http.ResponseWriter, err error) { + defer metrics.RequestHandled(metrics.RequestHandledLabelInvalid) + handleError(w, err) +} + +func (s *Server) handleWs(w http.ResponseWriter, req *http.Request) { + // CORS rule - Allow requests from anywhere + s.wsUpgrader.CheckOrigin = func(r *http.Request) bool { return true } + + // Upgrade the connection to a WS one + wsConn, err := s.wsUpgrader.Upgrade(w, req, nil) + if err != nil { + log.Error(fmt.Sprintf("Unable to upgrade to a WS connection, %s", err.Error())) + + return + } + + // Defer WS closure + defer func(ws *websocket.Conn) { + err = ws.Close() + if err != nil { + log.Error(fmt.Sprintf("Unable to gracefully close WS connection, %s", err.Error())) + } + }(wsConn) + + log.Info("Websocket connection established") + for { + msgType, message, err := wsConn.ReadMessage() + if err != nil { + if websocket.IsCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure, websocket.CloseAbnormalClosure) { + log.Info("Closing WS connection gracefully") + } else { + log.Error(fmt.Sprintf("Unable to read WS message, %s", err.Error())) + log.Info("Closing WS connection with error") + } + + s.handler.RemoveFilterByWsConn(wsConn) + + break + } + + if msgType == websocket.TextMessage || msgType == websocket.BinaryMessage { + go func() { + resp, err := s.handler.HandleWs(message, wsConn) + if err != nil { + log.Error(fmt.Sprintf("Unable to handle WS request, %s", err.Error())) + _ = wsConn.WriteMessage(msgType, []byte(fmt.Sprintf("WS Handle error: %s", err.Error()))) + } else { + _ = wsConn.WriteMessage(msgType, resp) + } + }() + } + } +} + func handleError(w http.ResponseWriter, err error) { log.Error(err) _, err = w.Write([]byte(err.Error())) @@ -255,11 +402,29 @@ func handleError(w http.ResponseWriter, err error) { } } -func rpcErrorResponse(code int, errorMessage string, err error) (interface{}, rpcError) { +func rpcErrorResponse(code int, message string, err error) (interface{}, types.Error) { + return rpcErrorResponseWithData(code, message, nil, err) +} + +func rpcErrorResponseWithData(code int, message string, data *[]byte, err error) (interface{}, types.Error) { if err != nil { - log.Errorf("%v:%v", errorMessage, err.Error()) + log.Errorf("%v:%v", message, err.Error()) } else { - log.Error(errorMessage) + log.Error(message) } - return nil, newRPCError(code, errorMessage) + return nil, types.NewRPCErrorWithData(code, message, data) +} + +func combinedLog(r *http.Request, start time.Time, httpStatus, dataLen int) { + log.Infof("%s - - %s \"%s %s %s\" %d %d \"%s\" \"%s\"", + r.RemoteAddr, + start.Format("[02/Jan/2006:15:04:05 -0700]"), + r.Method, + r.URL.Path, + r.Proto, + httpStatus, + dataLen, + r.Host, + r.UserAgent(), + ) } diff --git a/jsonrpc/server_test.go b/jsonrpc/server_test.go index f406b65188..45cbf80418 100644 --- a/jsonrpc/server_test.go +++ b/jsonrpc/server_test.go @@ -6,13 +6,18 @@ import ( "testing" "time" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/mocks" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) const ( - host = "localhost" - maxRequestsPerIPAndSecond = 1000 + maxRequestsPerIPAndSecond = 1000 + chainID uint64 = 1000 ) type mockedServer struct { @@ -21,20 +26,18 @@ type mockedServer struct { ServerURL string } -type mocks struct { - Pool *poolMock - State *stateMock - GasPriceEstimator *gasPriceEstimatorMock - Storage *storageMock - DbTx *dbTxMock +type mocksWrapper struct { + Pool *mocks.PoolMock + State *mocks.StateMock + Storage *storageMock + DbTx *mocks.DBTxMock } -func newMockedServer(t *testing.T, cfg Config) (*mockedServer, *mocks, *ethclient.Client) { - pool := newPoolMock(t) - state := newStateMock(t) - gasPriceEstimator := newGasPriceEstimatorMock(t) +func newMockedServer(t *testing.T, cfg Config) (*mockedServer, *mocksWrapper, *ethclient.Client) { + pool := mocks.NewPoolMock(t) + st := mocks.NewStateMock(t) storage := newStorageMock(t) - dbTx := newDbTxMock(t) + dbTx := mocks.NewDBTxMock(t) apis := map[string]bool{ APIEth: true, APINet: true, @@ -44,7 +47,11 @@ func newMockedServer(t *testing.T, cfg Config) (*mockedServer, *mocks, *ethclien APIWeb3: true, } - server := NewServer(cfg, pool, state, gasPriceEstimator, storage, apis) + var newL2BlockEventHandler state.NewL2BlockEventHandler = func(e state.NewL2BlockEvent) {} + st.On("RegisterNewL2BlockEventHandler", mock.IsType(newL2BlockEventHandler)).Once() + + st.On("PrepareWebSocket").Once() + server := NewServer(cfg, chainID, pool, st, storage, apis) go func() { err := server.Start() @@ -73,12 +80,11 @@ func newMockedServer(t *testing.T, cfg Config) (*mockedServer, *mocks, *ethclien ServerURL: serverURL, } - mks := &mocks{ - Pool: pool, - State: state, - GasPriceEstimator: gasPriceEstimator, - Storage: storage, - DbTx: dbTx, + mks := &mocksWrapper{ + Pool: pool, + State: st, + Storage: storage, + DbTx: dbTx, } return msv, mks, ethClient @@ -86,24 +92,22 @@ func newMockedServer(t *testing.T, cfg Config) (*mockedServer, *mocks, *ethclien func getDefaultConfig() Config { cfg := Config{ - Host: host, - Port: 8123, + Host: "0.0.0.0", + Port: 9123, MaxRequestsPerIPAndSecond: maxRequestsPerIPAndSecond, - DefaultSenderAddress: "0x1111111111111111111111111111111111111111", MaxCumulativeGasUsed: 300000, - ChainID: 1000, } return cfg } -func newSequencerMockedServer(t *testing.T) (*mockedServer, *mocks, *ethclient.Client) { +func newSequencerMockedServer(t *testing.T) (*mockedServer, *mocksWrapper, *ethclient.Client) { cfg := getDefaultConfig() return newMockedServer(t, cfg) } -func newNonSequencerMockedServer(t *testing.T, sequencerNodeURI string) (*mockedServer, *mocks, *ethclient.Client) { +func newNonSequencerMockedServer(t *testing.T, sequencerNodeURI string) (*mockedServer, *mocksWrapper, *ethclient.Client) { cfg := getDefaultConfig() - cfg.Port = 8124 + cfg.Port = 9124 cfg.SequencerNodeURI = sequencerNodeURI return newMockedServer(t, cfg) } @@ -115,6 +119,10 @@ func (s *mockedServer) Stop() { } } -func (s *mockedServer) JSONRPCCall(method string, parameters ...interface{}) (Response, error) { - return JSONRPCCall(s.ServerURL, method, parameters...) +func (s *mockedServer) JSONRPCCall(method string, parameters ...interface{}) (types.Response, error) { + return client.JSONRPCCall(s.ServerURL, method, parameters...) +} + +func (s *mockedServer) ChainID() uint64 { + return chainID } diff --git a/jsonrpc/storage.go b/jsonrpc/storage.go new file mode 100644 index 0000000000..32de18fc27 --- /dev/null +++ b/jsonrpc/storage.go @@ -0,0 +1,170 @@ +package jsonrpc + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/google/uuid" + "github.com/gorilla/websocket" +) + +// ErrNotFound represent a not found error. +var ErrNotFound = errors.New("object not found") + +// ErrFilterInvalidPayload indicates there is an invalid payload when creating a filter +var ErrFilterInvalidPayload = errors.New("invalid argument 0: cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other") + +// Storage uses memory to store the data +// related to the json rpc server +type Storage struct { + filters sync.Map +} + +// NewStorage creates and initializes an instance of Storage +func NewStorage() *Storage { + return &Storage{ + filters: sync.Map{}, + } +} + +// NewLogFilter persists a new log filter +func (s *Storage) NewLogFilter(wsConn *websocket.Conn, filter LogFilter) (string, error) { + if filter.BlockHash != nil && (filter.FromBlock != nil || filter.ToBlock != nil) { + return "", ErrFilterInvalidPayload + } + + return s.createFilter(FilterTypeLog, filter, wsConn) +} + +// NewBlockFilter persists a new block log filter +func (s *Storage) NewBlockFilter(wsConn *websocket.Conn) (string, error) { + return s.createFilter(FilterTypeBlock, nil, wsConn) +} + +// NewPendingTransactionFilter persists a new pending transaction filter +func (s *Storage) NewPendingTransactionFilter(wsConn *websocket.Conn) (string, error) { + return s.createFilter(FilterTypePendingTx, nil, wsConn) +} + +// create persists the filter to the memory and provides the filter id +func (s *Storage) createFilter(t FilterType, parameters interface{}, wsConn *websocket.Conn) (string, error) { + lastPoll := time.Now().UTC() + id, err := s.generateFilterID() + if err != nil { + return "", fmt.Errorf("failed to generate filter ID: %w", err) + } + s.filters.Store(id, &Filter{ + ID: id, + Type: t, + Parameters: parameters, + LastPoll: lastPoll, + WsConn: wsConn, + }) + + return id, nil +} + +func (s *Storage) generateFilterID() (string, error) { + r, err := uuid.NewRandom() + if err != nil { + return "", err + } + + b, err := r.MarshalBinary() + if err != nil { + return "", err + } + + id := hex.EncodeToHex(b) + return id, nil +} + +// GetAllBlockFiltersWithWSConn returns an array with all filter that have +// a web socket connection and are filtering by new blocks +func (s *Storage) GetAllBlockFiltersWithWSConn() ([]*Filter, error) { + filtersWithWSConn := []*Filter{} + s.filters.Range(func(key, value any) bool { + filter := value.(*Filter) + if filter.WsConn == nil || filter.Type != FilterTypeBlock { + return true + } + + f := filter + filtersWithWSConn = append(filtersWithWSConn, f) + return true + }) + + return filtersWithWSConn, nil +} + +// GetAllLogFiltersWithWSConn returns an array with all filter that have +// a web socket connection and are filtering by new logs +func (s *Storage) GetAllLogFiltersWithWSConn() ([]*Filter, error) { + filtersWithWSConn := []*Filter{} + s.filters.Range(func(key, value any) bool { + filter := value.(*Filter) + if filter.WsConn == nil || filter.Type != FilterTypeLog { + return true + } + + f := filter + filtersWithWSConn = append(filtersWithWSConn, f) + return true + }) + + return filtersWithWSConn, nil +} + +// GetFilter gets a filter by its id +func (s *Storage) GetFilter(filterID string) (*Filter, error) { + filter, found := s.filters.Load(filterID) + if !found { + return nil, ErrNotFound + } + + return filter.(*Filter), nil +} + +// UpdateFilterLastPoll updates the last poll to now +func (s *Storage) UpdateFilterLastPoll(filterID string) error { + filterValue, found := s.filters.Load(filterID) + if !found { + return ErrNotFound + } + filter := filterValue.(*Filter) + filter.LastPoll = time.Now().UTC() + s.filters.Store(filterID, filter) + return nil +} + +// UninstallFilter deletes a filter by its id +func (s *Storage) UninstallFilter(filterID string) error { + _, found := s.filters.Load(filterID) + if !found { + return ErrNotFound + } + s.filters.Delete(filterID) + return nil +} + +// UninstallFilterByWSConn deletes all filters connected to the provided web socket connection +func (s *Storage) UninstallFilterByWSConn(wsConn *websocket.Conn) error { + filterIDsToDelete := []string{} + s.filters.Range(func(key, value any) bool { + id := key.(string) + filter := value.(*Filter) + if filter.WsConn == wsConn { + filterIDsToDelete = append(filterIDsToDelete, id) + } + return true + }) + + for _, filterID := range filterIDsToDelete { + s.filters.Delete(filterID) + } + + return nil +} diff --git a/jsonrpc/types.go b/jsonrpc/types.go deleted file mode 100644 index 23ee2d792a..0000000000 --- a/jsonrpc/types.go +++ /dev/null @@ -1,398 +0,0 @@ -package jsonrpc - -import ( - "context" - "math/big" - "strconv" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/jackc/pgx/v4" -) - -type argUint64 uint64 - -// MarshalText marshals into text -func (b argUint64) MarshalText() ([]byte, error) { - buf := make([]byte, 2, encoding.Base10) //nolint:gomnd - copy(buf, `0x`) - buf = strconv.AppendUint(buf, uint64(b), hex.Base) - return buf, nil -} - -// UnmarshalText unmarshals from text -func (b *argUint64) UnmarshalText(input []byte) error { - str := strings.TrimPrefix(string(input), "0x") - num, err := strconv.ParseUint(str, hex.Base, encoding.BitSize64) - if err != nil { - return err - } - *b = argUint64(num) - return nil -} - -type argBytes []byte - -// MarshalText marshals into text -func (b argBytes) MarshalText() ([]byte, error) { - return encodeToHex(b), nil -} - -// UnmarshalText unmarshals from text -func (b *argBytes) UnmarshalText(input []byte) error { - hh, err := decodeToHex(input) - if err != nil { - return nil - } - aux := make([]byte, len(hh)) - copy(aux[:], hh[:]) - *b = aux - return nil -} - -func argBytesPtr(b []byte) *argBytes { - bb := argBytes(b) - - return &bb -} - -type argBig big.Int - -func (a *argBig) UnmarshalText(input []byte) error { - buf, err := decodeToHex(input) - if err != nil { - return err - } - - b := new(big.Int) - b.SetBytes(buf) - *a = argBig(*b) - - return nil -} - -func (a argBig) MarshalText() ([]byte, error) { - b := (*big.Int)(&a) - - return []byte("0x" + b.Text(hex.Base)), nil -} - -func decodeToHex(b []byte) ([]byte, error) { - str := string(b) - str = strings.TrimPrefix(str, "0x") - if len(str)%2 != 0 { - str = "0" + str - } - return hex.DecodeString(str) -} - -func encodeToHex(b []byte) []byte { - str := hex.EncodeToString(b) - if len(str)%2 != 0 { - str = "0" + str - } - return []byte("0x" + str) -} - -// txnArgs is the transaction argument for the rpc endpoints -type txnArgs struct { - From common.Address - To *common.Address - Gas *argUint64 - GasPrice *argUint64 - Value *argBytes - Data *argBytes -} - -// ToTransaction transforms txnArgs into a Transaction -func (args *txnArgs) ToUnsignedTransaction(ctx context.Context, st stateInterface, blockNumber uint64, cfg Config, dbTx pgx.Tx) (common.Address, *types.Transaction, error) { - gas := cfg.MaxCumulativeGasUsed - if args.Gas != nil && uint64(*args.Gas) > uint64(0) { - gas = uint64(*args.Gas) - } - - value := big.NewInt(0) - if args.Value != nil { - value.SetBytes(*args.Value) - } - - data := []byte{} - if args.Data != nil { - data = *args.Data - } - - sender := args.From - nonce := uint64(0) - gasPrice := big.NewInt(0) - - defaultSenderAddress := common.HexToAddress(cfg.DefaultSenderAddress) - if sender == state.ZeroAddress { - sender = defaultSenderAddress - } - - if sender != defaultSenderAddress { - if args.GasPrice != nil { - gasPrice.SetUint64(uint64(*args.GasPrice)) - } - - n, err := st.GetNonce(ctx, sender, blockNumber, dbTx) - if err != nil { - return common.Address{}, nil, err - } - nonce = uint64(n) - } - - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - To: args.To, - Value: value, - Gas: gas, - GasPrice: gasPrice, - Data: data, - }) - - return sender, tx, nil -} - -type rpcBlock struct { - ParentHash common.Hash `json:"parentHash"` - Sha3Uncles common.Hash `json:"sha3Uncles"` - Miner common.Address `json:"miner"` - StateRoot common.Hash `json:"stateRoot"` - TxRoot common.Hash `json:"transactionsRoot"` - ReceiptsRoot common.Hash `json:"receiptsRoot"` - LogsBloom types.Bloom `json:"logsBloom"` - Difficulty argUint64 `json:"difficulty"` - TotalDifficulty argUint64 `json:"totalDifficulty"` - Size argUint64 `json:"size"` - Number argUint64 `json:"number"` - GasLimit argUint64 `json:"gasLimit"` - GasUsed argUint64 `json:"gasUsed"` - Timestamp argUint64 `json:"timestamp"` - ExtraData argBytes `json:"extraData"` - MixHash common.Hash `json:"mixHash"` - Nonce argBytes `json:"nonce"` - Hash common.Hash `json:"hash"` - Transactions []rpcTransactionOrHash `json:"transactions"` - Uncles []common.Hash `json:"uncles"` -} - -func l2BlockToRPCBlock(b *types.Block, fullTx bool) *rpcBlock { - h := b.Header() - - n := big.NewInt(0).SetUint64(h.Nonce.Uint64()) - nonce := common.LeftPadBytes(n.Bytes(), 8) //nolint:gomnd - - var difficulty uint64 - if h.Difficulty != nil { - difficulty = h.Difficulty.Uint64() - } else { - difficulty = uint64(0) - } - - res := &rpcBlock{ - ParentHash: h.ParentHash, - Sha3Uncles: h.UncleHash, - Miner: h.Coinbase, - StateRoot: h.Root, - TxRoot: h.TxHash, - ReceiptsRoot: h.ReceiptHash, - LogsBloom: h.Bloom, - Difficulty: argUint64(difficulty), - TotalDifficulty: argUint64(difficulty), - Size: argUint64(b.Size()), - Number: argUint64(b.Number().Uint64()), - GasLimit: argUint64(h.GasLimit), - GasUsed: argUint64(h.GasUsed), - Timestamp: argUint64(h.Time), - ExtraData: argBytes(h.Extra), - MixHash: h.MixDigest, - Nonce: nonce, - Hash: b.Hash(), - Transactions: []rpcTransactionOrHash{}, - Uncles: []common.Hash{}, - } - - for idx, txn := range b.Transactions() { - if fullTx { - blockHash := b.Hash() - txIndex := uint64(idx) - tx := toRPCTransaction(txn, b.Number(), &blockHash, &txIndex) - res.Transactions = append( - res.Transactions, - tx, - ) - } else { - res.Transactions = append( - res.Transactions, - transactionHash(txn.Hash()), - ) - } - } - - for _, uncle := range b.Uncles() { - res.Uncles = append(res.Uncles, uncle.Hash()) - } - - return res -} - -// For union type of transaction and types.Hash -type rpcTransactionOrHash interface { - getHash() common.Hash -} - -type rpcTransaction struct { - Nonce argUint64 `json:"nonce"` - GasPrice argBig `json:"gasPrice"` - Gas argUint64 `json:"gas"` - To *common.Address `json:"to"` - Value argBig `json:"value"` - Input argBytes `json:"input"` - V argBig `json:"v"` - R argBig `json:"r"` - S argBig `json:"s"` - Hash common.Hash `json:"hash"` - From common.Address `json:"from"` - BlockHash *common.Hash `json:"blockHash"` - BlockNumber *argUint64 `json:"blockNumber"` - TxIndex *argUint64 `json:"transactionIndex"` -} - -func (t rpcTransaction) getHash() common.Hash { return t.Hash } - -// Redefine to implement getHash() of transactionOrHash -type transactionHash common.Hash - -func (h transactionHash) getHash() common.Hash { return common.Hash(h) } - -func (h transactionHash) MarshalText() ([]byte, error) { - return []byte(common.Hash(h).String()), nil -} - -func toRPCTransaction( - t *types.Transaction, - blockNumber *big.Int, - blockHash *common.Hash, - txIndex *uint64, -) *rpcTransaction { - v, r, s := t.RawSignatureValues() - - from, _ := state.GetSender(*t) - - res := &rpcTransaction{ - Nonce: argUint64(t.Nonce()), - GasPrice: argBig(*t.GasPrice()), - Gas: argUint64(t.Gas()), - To: t.To(), - Value: argBig(*t.Value()), - Input: t.Data(), - V: argBig(*v), - R: argBig(*r), - S: argBig(*s), - Hash: t.Hash(), - From: from, - } - - if blockNumber != nil { - bn := argUint64(blockNumber.Uint64()) - res.BlockNumber = &bn - } - - res.BlockHash = blockHash - - if txIndex != nil { - ti := argUint64(*txIndex) - res.TxIndex = &ti - } - - return res -} - -type rpcReceipt struct { - Root common.Hash `json:"root"` - CumulativeGasUsed argUint64 `json:"cumulativeGasUsed"` - LogsBloom types.Bloom `json:"logsBloom"` - Logs []*types.Log `json:"logs"` - Status argUint64 `json:"status"` - TxHash common.Hash `json:"transactionHash"` - TxIndex argUint64 `json:"transactionIndex"` - BlockHash common.Hash `json:"blockHash"` - BlockNumber argUint64 `json:"blockNumber"` - GasUsed argUint64 `json:"gasUsed"` - FromAddr common.Address `json:"from"` - ToAddr *common.Address `json:"to"` - ContractAddress *common.Address `json:"contractAddress"` - Type argUint64 `json:"type"` -} - -func receiptToRPCReceipt(tx types.Transaction, r *types.Receipt) (rpcReceipt, error) { - to := tx.To() - logs := r.Logs - if logs == nil { - logs = []*types.Log{} - } - - var contractAddress *common.Address - if r.ContractAddress != state.ZeroAddress { - ca := r.ContractAddress - contractAddress = &ca - } - - blockNumber := argUint64(0) - if r.BlockNumber != nil { - blockNumber = argUint64(r.BlockNumber.Uint64()) - } - - from, err := state.GetSender(tx) - if err != nil { - return rpcReceipt{}, err - } - - return rpcReceipt{ - Root: common.BytesToHash(r.PostState), - CumulativeGasUsed: argUint64(r.CumulativeGasUsed), - LogsBloom: r.Bloom, - Logs: logs, - Status: argUint64(r.Status), - TxHash: r.TxHash, - TxIndex: argUint64(r.TransactionIndex), - BlockHash: r.BlockHash, - BlockNumber: blockNumber, - GasUsed: argUint64(r.GasUsed), - ContractAddress: contractAddress, - FromAddr: from, - ToAddr: to, - Type: argUint64(r.Type), - }, nil -} - -type rpcLog struct { - Address common.Address `json:"address"` - Topics []common.Hash `json:"topics"` - Data argBytes `json:"data"` - BlockNumber argUint64 `json:"blockNumber"` - TxHash common.Hash `json:"transactionHash"` - TxIndex argUint64 `json:"transactionIndex"` - BlockHash common.Hash `json:"blockHash"` - LogIndex argUint64 `json:"logIndex"` - Removed bool `json:"removed"` -} - -func logToRPCLog(l types.Log) rpcLog { - return rpcLog{ - Address: l.Address, - Topics: l.Topics, - Data: l.Data, - BlockNumber: argUint64(l.BlockNumber), - TxHash: l.TxHash, - TxIndex: argUint64(l.TxIndex), - BlockHash: l.BlockHash, - LogIndex: argUint64(l.Index), - Removed: l.Removed, - } -} diff --git a/jsonrpc/types/codec.go b/jsonrpc/types/codec.go new file mode 100644 index 0000000000..8af467a598 --- /dev/null +++ b/jsonrpc/types/codec.go @@ -0,0 +1,416 @@ +package types + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/jackc/pgx/v4" +) + +const ( + // PendingBlockNumber represents the pending block number + PendingBlockNumber = BlockNumber(-3) + // LatestBlockNumber represents the latest block number + LatestBlockNumber = BlockNumber(-2) + // EarliestBlockNumber represents the earliest block number + EarliestBlockNumber = BlockNumber(-1) + // SafeBlockNumber represents the last virtualized block number + SafeBlockNumber = BlockNumber(-4) + // FinalizedBlockNumber represents the last verified block number + FinalizedBlockNumber = BlockNumber(-5) + + // LatestBatchNumber represents the latest batch number + LatestBatchNumber = BatchNumber(-2) + // EarliestBatchNumber represents the earliest batch number + EarliestBatchNumber = BatchNumber(-1) + + // Earliest contains the string to represent the earliest block known. + Earliest = "earliest" + // Latest contains the string to represent the latest block known. + Latest = "latest" + // Pending contains the string to represent the pending block known. + Pending = "pending" + // Safe contains the string to represent the last virtualized block known. + Safe = "safe" + // Finalized contains the string to represent the last verified block known. + Finalized = "finalized" + + // EIP-1898: https://eips.ethereum.org/EIPS/eip-1898 // + + // BlockNumberKey is the key for the block number for EIP-1898 + BlockNumberKey = "blockNumber" + // BlockHashKey is the key for the block hash for EIP-1898 + BlockHashKey = "blockHash" + // RequireCanonicalKey is the key for the require canonical for EIP-1898 + RequireCanonicalKey = "requireCanonical" +) + +// Request is a jsonrpc request +type Request struct { + JSONRPC string `json:"jsonrpc"` + ID interface{} `json:"id"` + Method string `json:"method"` + Params json.RawMessage `json:"params,omitempty"` +} + +// Response is a jsonrpc success response +type Response struct { + JSONRPC string + ID interface{} + Result json.RawMessage + Error *ErrorObject +} + +// ErrorObject is a jsonrpc error +type ErrorObject struct { + Code int `json:"code"` + Message string `json:"message"` + Data *ArgBytes `json:"data,omitempty"` +} + +// NewResponse returns Success/Error response object +func NewResponse(req Request, reply []byte, err Error) Response { + var result json.RawMessage + if reply != nil { + result = reply + } + + var errorObj *ErrorObject + if err != nil { + errorObj = &ErrorObject{ + Code: err.ErrorCode(), + Message: err.Error(), + } + if err.ErrorData() != nil { + errorObj.Data = ArgBytesPtr(*err.ErrorData()) + } + } + + return Response{ + JSONRPC: req.JSONRPC, + ID: req.ID, + Result: result, + Error: errorObj, + } +} + +// MarshalJSON customizes the JSON representation of the response. +func (r Response) MarshalJSON() ([]byte, error) { + if r.Error != nil { + return json.Marshal(struct { + JSONRPC string `json:"jsonrpc"` + ID interface{} `json:"id"` + Error *ErrorObject `json:"error"` + }{ + JSONRPC: r.JSONRPC, + ID: r.ID, + Error: r.Error, + }) + } + + return json.Marshal(struct { + JSONRPC string `json:"jsonrpc"` + ID interface{} `json:"id"` + Result json.RawMessage `json:"result"` + }{ + JSONRPC: r.JSONRPC, + ID: r.ID, + Result: r.Result, + }) +} + +// Bytes return the serialized response +func (s Response) Bytes() ([]byte, error) { + return json.Marshal(s) +} + +// SubscriptionResponse used to push response for filters +// that have an active web socket connection +type SubscriptionResponse struct { + JSONRPC string `json:"jsonrpc"` + Method string `json:"method"` + Params SubscriptionResponseParams `json:"params"` +} + +// SubscriptionResponseParams parameters for subscription responses +type SubscriptionResponseParams struct { + Subscription string `json:"subscription"` + Result json.RawMessage `json:"result"` +} + +// Bytes return the serialized response +func (s SubscriptionResponse) Bytes() ([]byte, error) { + return json.Marshal(s) +} + +// BlockNumber is the number of a ethereum block +type BlockNumber int64 + +// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called +func (b *BlockNumber) UnmarshalJSON(buffer []byte) error { + num, err := StringToBlockNumber(string(buffer)) + if err != nil { + return err + } + *b = num + return nil +} + +// GetNumericBlockNumber returns a numeric block number based on the BlockNumber instance +func (b *BlockNumber) GetNumericBlockNumber(ctx context.Context, s StateInterface, dbTx pgx.Tx) (uint64, Error) { + bValue := LatestBlockNumber + if b != nil { + bValue = *b + } + + switch bValue { + case LatestBlockNumber, PendingBlockNumber: + lastBlockNumber, err := s.GetLastL2BlockNumber(ctx, dbTx) + if err != nil { + return 0, NewRPCError(DefaultErrorCode, "failed to get the last block number from state") + } + + return lastBlockNumber, nil + + case EarliestBlockNumber: + return 0, nil + + case SafeBlockNumber: + lastBlockNumber, err := s.GetLastVirtualizedL2BlockNumber(ctx, dbTx) + if err != nil { + return 0, NewRPCError(DefaultErrorCode, "failed to get the last virtualized block number from state") + } + + return lastBlockNumber, nil + + case FinalizedBlockNumber: + lastBlockNumber, err := s.GetLastConsolidatedL2BlockNumber(ctx, dbTx) + if err != nil { + return 0, NewRPCError(DefaultErrorCode, "failed to get the last verified block number from state") + } + + return lastBlockNumber, nil + + default: + if bValue < 0 { + return 0, NewRPCError(InvalidParamsErrorCode, "invalid block number: %v", bValue) + } + return uint64(bValue), nil + } +} + +// StringOrHex returns the block number as a string or hex +// n == -3 = pending +// n == -2 = latest +// n == -1 = earliest +// n >= 0 = hex(n) +func (b *BlockNumber) StringOrHex() string { + switch *b { + case EarliestBlockNumber: + return Earliest + case PendingBlockNumber: + return Pending + case LatestBlockNumber: + return Latest + case SafeBlockNumber: + return Safe + case FinalizedBlockNumber: + return Finalized + default: + return hex.EncodeUint64(uint64(*b)) + } +} + +// StringToBlockNumber converts a string like "latest" or "0x1" to a BlockNumber instance +func StringToBlockNumber(str string) (BlockNumber, error) { + str = strings.Trim(str, "\"") + switch str { + case Earliest: + return EarliestBlockNumber, nil + case Pending: + return PendingBlockNumber, nil + case Latest, "": + return LatestBlockNumber, nil + case Safe: + return SafeBlockNumber, nil + case Finalized: + return FinalizedBlockNumber, nil + } + + n, err := encoding.DecodeUint64orHex(&str) + if err != nil { + return 0, err + } + return BlockNumber(n), nil +} + +// BlockNumberOrHash allows a string value to be parsed +// into a block number or a hash, it's used by methods +// like eth_call that allows the block to be specified +// either by the block number or the block hash +type BlockNumberOrHash struct { + number *BlockNumber + hash *ArgHash + requireCanonical bool +} + +// IsHash checks if the hash has value +func (b *BlockNumberOrHash) IsHash() bool { + return b.hash != nil +} + +// IsNumber checks if the number has value +func (b *BlockNumberOrHash) IsNumber() bool { + return b.number != nil +} + +// SetHash sets the hash and nullify the number +func (b *BlockNumberOrHash) SetHash(hash ArgHash, requireCanonical bool) { + t := hash + b.number = nil + b.hash = &t + b.requireCanonical = requireCanonical +} + +// SetNumber sets the number and nullify the hash +func (b *BlockNumberOrHash) SetNumber(number BlockNumber) { + t := number + b.number = &t + b.hash = nil + b.requireCanonical = false +} + +// Hash returns the hash +func (b *BlockNumberOrHash) Hash() *ArgHash { + return b.hash +} + +// Number returns the number +func (b *BlockNumberOrHash) Number() *BlockNumber { + return b.number +} + +// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called +func (b *BlockNumberOrHash) UnmarshalJSON(buffer []byte) error { + var number BlockNumber + err := json.Unmarshal(buffer, &number) + if err == nil { + b.SetNumber(number) + return nil + } + + var hash ArgHash + err = json.Unmarshal(buffer, &hash) + if err == nil { + b.SetHash(hash, false) + return nil + } + + var m map[string]interface{} + err = json.Unmarshal(buffer, &m) + if err == nil { + if v, ok := m[BlockNumberKey]; ok { + input, _ := json.Marshal(v.(string)) + err := json.Unmarshal(input, &number) + if err == nil { + b.SetNumber(number) + return nil + } + } else if v, ok := m[BlockHashKey]; ok { + input, _ := json.Marshal(v.(string)) + err := json.Unmarshal(input, &hash) + if err == nil { + requireCanonical, ok := m[RequireCanonicalKey] + if ok { + switch v := requireCanonical.(type) { + case bool: + b.SetHash(hash, v) + default: + return fmt.Errorf("invalid requiredCanonical") + } + } else { + b.SetHash(hash, false) + } + return nil + } + } else { + return fmt.Errorf("invalid block or hash") + } + } + + return err +} + +// Index of a item +type Index int64 + +// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called +func (i *Index) UnmarshalJSON(buffer []byte) error { + str := strings.Trim(string(buffer), "\"") + n, err := encoding.DecodeUint64orHex(&str) + if err != nil { + return err + } + *i = Index(n) + return nil +} + +// BatchNumber is the number of a ethereum block +type BatchNumber int64 + +// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called +func (b *BatchNumber) UnmarshalJSON(buffer []byte) error { + num, err := stringToBatchNumber(string(buffer)) + if err != nil { + return err + } + *b = num + return nil +} + +// GetNumericBatchNumber returns a numeric batch number based on the BatchNumber instance +func (b *BatchNumber) GetNumericBatchNumber(ctx context.Context, s StateInterface, dbTx pgx.Tx) (uint64, Error) { + bValue := LatestBatchNumber + if b != nil { + bValue = *b + } + + switch bValue { + case LatestBatchNumber: + lastBatchNumber, err := s.GetLastBatchNumber(ctx, dbTx) + if err != nil { + return 0, NewRPCError(DefaultErrorCode, "failed to get the last batch number from state") + } + + return lastBatchNumber, nil + + case EarliestBatchNumber: + return 0, nil + + default: + if bValue < 0 { + return 0, NewRPCError(InvalidParamsErrorCode, "invalid batch number: %v", bValue) + } + return uint64(bValue), nil + } +} + +func stringToBatchNumber(str string) (BatchNumber, error) { + str = strings.Trim(str, "\"") + switch str { + case Earliest: + return EarliestBatchNumber, nil + case Latest, "": + return LatestBatchNumber, nil + } + + n, err := encoding.DecodeUint64orHex(&str) + if err != nil { + return 0, err + } + return BatchNumber(n), nil +} diff --git a/jsonrpc/codec_test.go b/jsonrpc/types/codec_test.go similarity index 65% rename from jsonrpc/codec_test.go rename to jsonrpc/types/codec_test.go index 028ef6833b..76c03e4274 100644 --- a/jsonrpc/codec_test.go +++ b/jsonrpc/types/codec_test.go @@ -1,4 +1,4 @@ -package jsonrpc +package types import ( "context" @@ -6,6 +6,7 @@ import ( "strconv" "testing" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/mocks" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -19,6 +20,8 @@ func TestBlockNumberMarshalJSON(t *testing.T) { {"latest", int64(LatestBlockNumber), nil}, {"pending", int64(PendingBlockNumber), nil}, {"earliest", int64(EarliestBlockNumber), nil}, + {"safe", int64(SafeBlockNumber), nil}, + {"finalized", int64(FinalizedBlockNumber), nil}, {"", int64(LatestBlockNumber), nil}, {"0", int64(0), nil}, {"10", int64(10), nil}, @@ -40,14 +43,14 @@ func TestBlockNumberMarshalJSON(t *testing.T) { } func TestGetNumericBlockNumber(t *testing.T) { - s := newStateMock(t) + s := mocks.NewStateMock(t) type testCase struct { name string bn *BlockNumber expectedBlockNumber uint64 - expectedError rpcError - setupMocks func(s *stateMock, d *dbTxMock, t *testCase) + expectedError Error + setupMocks func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) } testCases := []testCase{ @@ -56,7 +59,7 @@ func TestGetNumericBlockNumber(t *testing.T) { bn: nil, expectedBlockNumber: 40, expectedError: nil, - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) { + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) { s. On("GetLastL2BlockNumber", context.Background(), d). Return(uint64(40), nil). @@ -68,7 +71,7 @@ func TestGetNumericBlockNumber(t *testing.T) { bn: bnPtr(LatestBlockNumber), expectedBlockNumber: 50, expectedError: nil, - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) { + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) { s. On("GetLastL2BlockNumber", context.Background(), d). Return(uint64(50), nil). @@ -80,7 +83,7 @@ func TestGetNumericBlockNumber(t *testing.T) { bn: bnPtr(PendingBlockNumber), expectedBlockNumber: 30, expectedError: nil, - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) { + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) { s. On("GetLastL2BlockNumber", context.Background(), d). Return(uint64(30), nil). @@ -92,30 +95,54 @@ func TestGetNumericBlockNumber(t *testing.T) { bn: bnPtr(EarliestBlockNumber), expectedBlockNumber: 0, expectedError: nil, - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) {}, + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) {}, + }, + { + name: "BlockNumber SafeBlockNumber", + bn: bnPtr(SafeBlockNumber), + expectedBlockNumber: 40, + expectedError: nil, + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) { + s. + On("GetLastVirtualizedL2BlockNumber", context.Background(), d). + Return(uint64(40), nil). + Once() + }, + }, + { + name: "BlockNumber FinalizedBlockNumber", + bn: bnPtr(FinalizedBlockNumber), + expectedBlockNumber: 50, + expectedError: nil, + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) { + s. + On("GetLastConsolidatedL2BlockNumber", context.Background(), d). + Return(uint64(50), nil). + Once() + }, }, { name: "BlockNumber Positive Number", bn: bnPtr(BlockNumber(int64(10))), expectedBlockNumber: 10, expectedError: nil, - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) {}, + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) {}, }, { - name: "BlockNumber Negative Number <= -4", - bn: bnPtr(BlockNumber(int64(-4))), + name: "BlockNumber Negative Number <= -6", + bn: bnPtr(BlockNumber(int64(-6))), expectedBlockNumber: 0, - expectedError: newRPCError(invalidParamsErrorCode, "invalid block number: -4"), - setupMocks: func(s *stateMock, d *dbTxMock, t *testCase) {}, + expectedError: NewRPCError(InvalidParamsErrorCode, "invalid block number: -6"), + setupMocks: func(s *mocks.StateMock, d *mocks.DBTxMock, t *testCase) {}, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { tc := testCase - dbTx := newDbTxMock(t) + dbTx := mocks.NewDBTxMock(t) testCase.setupMocks(s, dbTx, &tc) - result, rpcErr := testCase.bn.getNumericBlockNumber(context.Background(), s, dbTx) + result, rpcErr := testCase.bn.GetNumericBlockNumber(context.Background(), s, dbTx) assert.Equal(t, testCase.expectedBlockNumber, result) if rpcErr != nil || testCase.expectedError != nil { assert.Equal(t, testCase.expectedError.ErrorCode(), rpcErr.ErrorCode()) @@ -131,7 +158,7 @@ func TestResponseMarshal(t *testing.T) { JSONRPC string ID interface{} Result interface{} - Error rpcError + Error Error ExpectedJSON string }{ @@ -151,7 +178,7 @@ func TestResponseMarshal(t *testing.T) { JSONRPC: "2.0", ID: 1, Result: nil, - Error: newRPCError(123, "m"), + Error: NewRPCError(123, "m"), ExpectedJSON: "{\"jsonrpc\":\"2.0\",\"id\":1,\"error\":{\"code\":123,\"message\":\"m\"}}", }, @@ -162,7 +189,7 @@ func TestResponseMarshal(t *testing.T) { Result: struct { A string `json:"A"` }{"A"}, - Error: newRPCError(123, "m"), + Error: NewRPCError(123, "m"), ExpectedJSON: "{\"jsonrpc\":\"2.0\",\"id\":1,\"error\":{\"code\":123,\"message\":\"m\"}}", }, @@ -174,11 +201,11 @@ func TestResponseMarshal(t *testing.T) { JSONRPC: testCase.JSONRPC, ID: testCase.ID, } - var result *[]byte + var result []byte if testCase.Result != nil { r, err := json.Marshal(testCase.Result) require.NoError(t, err) - result = &r + result = r } res := NewResponse(req, result, testCase.Error) @@ -215,6 +242,24 @@ func TestIndexUnmarshalJSON(t *testing.T) { } } +func TestBlockNumberStringOrHex(t *testing.T) { + testCases := []struct { + bn *BlockNumber + expectedResult string + }{ + {bn: bnPtr(BlockNumber(-3)), expectedResult: "pending"}, + {bn: bnPtr(BlockNumber(-2)), expectedResult: "latest"}, + {bn: bnPtr(BlockNumber(-1)), expectedResult: "earliest"}, + {bn: bnPtr(BlockNumber(0)), expectedResult: "0x0"}, + {bn: bnPtr(BlockNumber(100)), expectedResult: "0x64"}, + } + + for _, testCase := range testCases { + result := testCase.bn.StringOrHex() + assert.Equal(t, testCase.expectedResult, result) + } +} + func bnPtr(bn BlockNumber) *BlockNumber { return &bn } diff --git a/jsonrpc/types/errors.go b/jsonrpc/types/errors.go new file mode 100644 index 0000000000..17e095094c --- /dev/null +++ b/jsonrpc/types/errors.go @@ -0,0 +1,63 @@ +package types + +import "fmt" + +const ( + // DefaultErrorCode rpc default error code + DefaultErrorCode = -32000 + // RevertedErrorCode error code for reverted txs + RevertedErrorCode = 3 + // InvalidRequestErrorCode error code for invalid requests + InvalidRequestErrorCode = -32600 + // NotFoundErrorCode error code for not found objects + NotFoundErrorCode = -32601 + // InvalidParamsErrorCode error code for invalid parameters + InvalidParamsErrorCode = -32602 + // ParserErrorCode error code for parsing errors + ParserErrorCode = -32700 +) + +// Error interface +type Error interface { + Error() string + ErrorCode() int + ErrorData() *[]byte +} + +// RPCError represents an error returned by a JSON RPC endpoint. +type RPCError struct { + err string + code int + data *[]byte +} + +// NewRPCError creates a new error instance to be returned by the RPC endpoints +func NewRPCError(code int, err string, args ...interface{}) *RPCError { + return NewRPCErrorWithData(code, err, nil, args...) +} + +// NewRPCErrorWithData creates a new error instance with data to be returned by the RPC endpoints +func NewRPCErrorWithData(code int, err string, data *[]byte, args ...interface{}) *RPCError { + var errMessage string + if len(args) > 0 { + errMessage = fmt.Sprintf(err, args...) + } else { + errMessage = err + } + return &RPCError{code: code, err: errMessage, data: data} +} + +// Error returns the error message. +func (e *RPCError) Error() string { + return e.err +} + +// ErrorCode returns the error code. +func (e *RPCError) ErrorCode() int { + return e.code +} + +// ErrorData returns the error data. +func (e *RPCError) ErrorData() *[]byte { + return e.data +} diff --git a/jsonrpc/types/errors_test.go b/jsonrpc/types/errors_test.go new file mode 100644 index 0000000000..1359da4584 --- /dev/null +++ b/jsonrpc/types/errors_test.go @@ -0,0 +1,24 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestErrorConstants(t *testing.T) { + assert.Equal(t, -32000, DefaultErrorCode) + assert.Equal(t, -32600, InvalidRequestErrorCode) + assert.Equal(t, -32601, NotFoundErrorCode) + assert.Equal(t, -32602, InvalidParamsErrorCode) + assert.Equal(t, -32700, ParserErrorCode) +} + +func TestErrorMethods(t *testing.T) { + const code, msg = 1, "err" + + var err Error = NewRPCError(code, msg) + + assert.Equal(t, code, err.ErrorCode()) + assert.Equal(t, msg, err.Error()) +} diff --git a/jsonrpc/types/interfaces.go b/jsonrpc/types/interfaces.go new file mode 100644 index 0000000000..f6d516b87e --- /dev/null +++ b/jsonrpc/types/interfaces.go @@ -0,0 +1,66 @@ +package types + +import ( + "context" + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +// PoolInterface contains the methods required to interact with the tx pool. +type PoolInterface interface { + AddTx(ctx context.Context, tx types.Transaction, ip string) error + GetGasPrice(ctx context.Context) (uint64, error) + GetNonce(ctx context.Context, address common.Address) (uint64, error) + GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) + GetPendingTxs(ctx context.Context, limit uint64) ([]pool.Transaction, error) + CountPendingTransactions(ctx context.Context) (uint64, error) + GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Transaction, error) +} + +// StateInterface gathers the methods required to interact with the state. +type StateInterface interface { + PrepareWebSocket() + BeginStateTransaction(ctx context.Context) (pgx.Tx, error) + DebugTransaction(ctx context.Context, transactionHash common.Hash, traceConfig state.TraceConfig, dbTx pgx.Tx) (*runtime.ExecutionResult, error) + EstimateGas(transaction *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error) + GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) + GetCode(ctx context.Context, address common.Address, root common.Hash) ([]byte, error) + GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*types.Block, error) + GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Block, error) + BatchNumberByL2BlockNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) + GetL2BlockHashesSince(ctx context.Context, since time.Time, dbTx pgx.Tx) ([]common.Hash, error) + GetL2BlockHeaderByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Header, error) + GetL2BlockTransactionCountByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (uint64, error) + GetL2BlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) + GetLastVirtualizedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLastConsolidatedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) + GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*types.Log, error) + GetNonce(ctx context.Context, address common.Address, root common.Hash) (uint64, error) + GetStorageAt(ctx context.Context, address common.Address, position *big.Int, root common.Hash) (*big.Int, error) + GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (state.SyncingInfo, error) + GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) + GetTransactionByL2BlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) + GetTransactionByL2BlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) + GetTransactionReceipt(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Receipt, error) + IsL2BlockConsolidated(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) + IsL2BlockVirtualized(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) + ProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) (*runtime.ExecutionResult, error) + RegisterNewL2BlockEventHandler(h state.NewL2BlockEventHandler) + GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) + GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (txs []types.Transaction, err error) + GetVirtualBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.VirtualBatch, error) + GetVerifiedBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.VerifiedBatch, error) + GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*state.GlobalExitRoot, error) +} diff --git a/jsonrpc/types/query.go b/jsonrpc/types/query.go new file mode 100644 index 0000000000..2b6429284f --- /dev/null +++ b/jsonrpc/types/query.go @@ -0,0 +1,14 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/common" +) + +// LogFilterRequest represents a log filter request. +type LogFilterRequest struct { + BlockHash *common.Hash `json:"blockHash,omitempty"` + FromBlock *string `json:"fromBlock,omitempty"` + ToBlock *string `json:"toBlock,omitempty"` + Address interface{} `json:"address,omitempty"` + Topics []interface{} `json:"topics,omitempty"` +} diff --git a/jsonrpc/types/types.go b/jsonrpc/types/types.go new file mode 100644 index 0000000000..1a0d0997ae --- /dev/null +++ b/jsonrpc/types/types.go @@ -0,0 +1,595 @@ +package types + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "strconv" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +// ArgUint64 helps to marshal uint64 values provided in the RPC requests +type ArgUint64 uint64 + +// MarshalText marshals into text +func (b ArgUint64) MarshalText() ([]byte, error) { + buf := make([]byte, 2) //nolint:gomnd + copy(buf, `0x`) + buf = strconv.AppendUint(buf, uint64(b), hex.Base) + return buf, nil +} + +// UnmarshalText unmarshals from text +func (b *ArgUint64) UnmarshalText(input []byte) error { + str := strings.TrimPrefix(string(input), "0x") + num, err := strconv.ParseUint(str, hex.Base, hex.BitSize64) + if err != nil { + return err + } + *b = ArgUint64(num) + return nil +} + +// Hex returns a hexadecimal representation +func (b ArgUint64) Hex() string { + bb, _ := b.MarshalText() + return string(bb) +} + +// ArgUint64Ptr returns the pointer of the provided ArgUint64 +func ArgUint64Ptr(a ArgUint64) *ArgUint64 { + return &a +} + +// ArgBytes helps to marshal byte array values provided in the RPC requests +type ArgBytes []byte + +// MarshalText marshals into text +func (b ArgBytes) MarshalText() ([]byte, error) { + return encodeToHex(b), nil +} + +// UnmarshalText unmarshals from text +func (b *ArgBytes) UnmarshalText(input []byte) error { + hh, err := decodeToHex(input) + if err != nil { + return nil + } + aux := make([]byte, len(hh)) + copy(aux[:], hh[:]) + *b = aux + return nil +} + +// Hex returns a hexadecimal representation +func (b ArgBytes) Hex() string { + bb, _ := b.MarshalText() + return string(bb) +} + +// ArgBytesPtr helps to marshal byte array values provided in the RPC requests +func ArgBytesPtr(b []byte) *ArgBytes { + bb := ArgBytes(b) + + return &bb +} + +// ArgBig helps to marshal big number values provided in the RPC requests +type ArgBig big.Int + +// UnmarshalText unmarshals an instance of ArgBig into an array of bytes +func (a *ArgBig) UnmarshalText(input []byte) error { + buf, err := decodeToHex(input) + if err != nil { + return err + } + + b := new(big.Int) + b.SetBytes(buf) + *a = ArgBig(*b) + + return nil +} + +// MarshalText marshals an array of bytes into an instance of ArgBig +func (a ArgBig) MarshalText() ([]byte, error) { + b := (*big.Int)(&a) + + return []byte("0x" + b.Text(hex.Base)), nil +} + +// Hex returns a hexadecimal representation +func (b ArgBig) Hex() string { + bb, _ := b.MarshalText() + return string(bb) +} + +func decodeToHex(b []byte) ([]byte, error) { + str := string(b) + str = strings.TrimPrefix(str, "0x") + if len(str)%2 != 0 { + str = "0" + str + } + return hex.DecodeString(str) +} + +func encodeToHex(b []byte) []byte { + str := hex.EncodeToString(b) + if len(str)%2 != 0 { + str = "0" + str + } + return []byte("0x" + str) +} + +// ArgHash represents a common.Hash that accepts strings +// shorter than 64 bytes, like 0x00 +type ArgHash common.Hash + +// UnmarshalText unmarshals from text +func (arg *ArgHash) UnmarshalText(input []byte) error { + if !hex.IsValid(string(input)) { + return fmt.Errorf("invalid hash, it needs to be a hexadecimal value") + } + + str := strings.TrimPrefix(string(input), "0x") + *arg = ArgHash(common.HexToHash(str)) + return nil +} + +// Hash returns an instance of common.Hash +func (arg *ArgHash) Hash() common.Hash { + result := common.Hash{} + if arg != nil { + result = common.Hash(*arg) + } + return result +} + +// ArgAddress represents a common.Address that accepts strings +// shorter than 32 bytes, like 0x00 +type ArgAddress common.Address + +// UnmarshalText unmarshals from text +func (b *ArgAddress) UnmarshalText(input []byte) error { + if !hex.IsValid(string(input)) { + return fmt.Errorf("invalid address, it needs to be a hexadecimal value") + } + + str := strings.TrimPrefix(string(input), "0x") + *b = ArgAddress(common.HexToAddress(str)) + return nil +} + +// Address returns an instance of common.Address +func (arg *ArgAddress) Address() common.Address { + result := common.Address{} + if arg != nil { + result = common.Address(*arg) + } + return result +} + +// TxArgs is the transaction argument for the rpc endpoints +type TxArgs struct { + From *common.Address + To *common.Address + Gas *ArgUint64 + GasPrice *ArgBytes + Value *ArgBytes + Data *ArgBytes + Input *ArgBytes + Nonce *ArgUint64 +} + +// ToTransaction transforms txnArgs into a Transaction +func (args *TxArgs) ToTransaction(ctx context.Context, st StateInterface, maxCumulativeGasUsed uint64, root common.Hash, defaultSenderAddress common.Address, dbTx pgx.Tx) (common.Address, *types.Transaction, error) { + sender := defaultSenderAddress + nonce := uint64(0) + if args.From != nil && *args.From != state.ZeroAddress { + sender = *args.From + n, err := st.GetNonce(ctx, sender, root) + if err != nil { + return common.Address{}, nil, err + } + nonce = n + } + + value := big.NewInt(0) + if args.Value != nil { + value.SetBytes(*args.Value) + } + + gasPrice := big.NewInt(0) + if args.GasPrice != nil { + gasPrice.SetBytes(*args.GasPrice) + } + + var data []byte + if args.Data != nil { + data = *args.Data + } else if args.Input != nil { + data = *args.Input + } else if args.To == nil { + return common.Address{}, nil, fmt.Errorf("contract creation without data provided") + } + + gas := maxCumulativeGasUsed + if args.Gas != nil && uint64(*args.Gas) > 0 && uint64(*args.Gas) < maxCumulativeGasUsed { + gas = uint64(*args.Gas) + } + + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: args.To, + Value: value, + Gas: gas, + GasPrice: gasPrice, + Data: data, + }) + + return sender, tx, nil +} + +// Block structure +type Block struct { + ParentHash common.Hash `json:"parentHash"` + Sha3Uncles common.Hash `json:"sha3Uncles"` + Miner common.Address `json:"miner"` + StateRoot common.Hash `json:"stateRoot"` + TxRoot common.Hash `json:"transactionsRoot"` + ReceiptsRoot common.Hash `json:"receiptsRoot"` + LogsBloom types.Bloom `json:"logsBloom"` + Difficulty ArgUint64 `json:"difficulty"` + TotalDifficulty ArgUint64 `json:"totalDifficulty"` + Size ArgUint64 `json:"size"` + Number ArgUint64 `json:"number"` + GasLimit ArgUint64 `json:"gasLimit"` + GasUsed ArgUint64 `json:"gasUsed"` + Timestamp ArgUint64 `json:"timestamp"` + ExtraData ArgBytes `json:"extraData"` + MixHash common.Hash `json:"mixHash"` + Nonce ArgBytes `json:"nonce"` + Hash common.Hash `json:"hash"` + Transactions []TransactionOrHash `json:"transactions"` + Uncles []common.Hash `json:"uncles"` +} + +// NewBlock creates a Block instance +func NewBlock(b *types.Block, fullTx bool) *Block { + h := b.Header() + + n := big.NewInt(0).SetUint64(h.Nonce.Uint64()) + nonce := common.LeftPadBytes(n.Bytes(), 8) //nolint:gomnd + + var difficulty uint64 + if h.Difficulty != nil { + difficulty = h.Difficulty.Uint64() + } else { + difficulty = uint64(0) + } + + res := &Block{ + ParentHash: h.ParentHash, + Sha3Uncles: h.UncleHash, + Miner: h.Coinbase, + StateRoot: h.Root, + TxRoot: h.TxHash, + ReceiptsRoot: h.ReceiptHash, + LogsBloom: h.Bloom, + Difficulty: ArgUint64(difficulty), + TotalDifficulty: ArgUint64(difficulty), + Size: ArgUint64(b.Size()), + Number: ArgUint64(b.Number().Uint64()), + GasLimit: ArgUint64(h.GasLimit), + GasUsed: ArgUint64(h.GasUsed), + Timestamp: ArgUint64(h.Time), + ExtraData: ArgBytes(h.Extra), + MixHash: h.MixDigest, + Nonce: nonce, + Hash: b.Hash(), + Transactions: []TransactionOrHash{}, + Uncles: []common.Hash{}, + } + + for idx, txn := range b.Transactions() { + if fullTx { + blockHash := b.Hash() + txIndex := uint64(idx) + tx := NewTransaction(*txn, b.Number(), &blockHash, &txIndex) + res.Transactions = append( + res.Transactions, + TransactionOrHash{Tx: tx}, + ) + } else { + h := txn.Hash() + res.Transactions = append( + res.Transactions, + TransactionOrHash{Hash: &h}, + ) + } + } + + for _, uncle := range b.Uncles() { + res.Uncles = append(res.Uncles, uncle.Hash()) + } + + return res +} + +// Batch structure +type Batch struct { + Number ArgUint64 `json:"number"` + Coinbase common.Address `json:"coinbase"` + StateRoot common.Hash `json:"stateRoot"` + GlobalExitRoot common.Hash `json:"globalExitRoot"` + MainnetExitRoot common.Hash `json:"mainnetExitRoot"` + RollupExitRoot common.Hash `json:"rollupExitRoot"` + LocalExitRoot common.Hash `json:"localExitRoot"` + AccInputHash common.Hash `json:"accInputHash"` + Timestamp ArgUint64 `json:"timestamp"` + SendSequencesTxHash *common.Hash `json:"sendSequencesTxHash"` + VerifyBatchTxHash *common.Hash `json:"verifyBatchTxHash"` + Transactions []TransactionOrHash `json:"transactions"` +} + +// NewBatch creates a Batch instance +func NewBatch(batch *state.Batch, virtualBatch *state.VirtualBatch, verifiedBatch *state.VerifiedBatch, receipts []types.Receipt, fullTx bool, ger *state.GlobalExitRoot) *Batch { + res := &Batch{ + Number: ArgUint64(batch.BatchNumber), + GlobalExitRoot: batch.GlobalExitRoot, + MainnetExitRoot: ger.MainnetExitRoot, + RollupExitRoot: ger.RollupExitRoot, + AccInputHash: batch.AccInputHash, + Timestamp: ArgUint64(batch.Timestamp.Unix()), + StateRoot: batch.StateRoot, + Coinbase: batch.Coinbase, + LocalExitRoot: batch.LocalExitRoot, + } + + if virtualBatch != nil { + res.SendSequencesTxHash = &virtualBatch.TxHash + } + + if verifiedBatch != nil { + res.VerifyBatchTxHash = &verifiedBatch.TxHash + } + + receiptsMap := make(map[common.Hash]types.Receipt, len(receipts)) + for _, receipt := range receipts { + receiptsMap[receipt.TxHash] = receipt + } + + for _, tx := range batch.Transactions { + if fullTx { + receipt := receiptsMap[tx.Hash()] + txIndex := uint64(receipt.TransactionIndex) + rpcTx := NewTransaction(tx, receipt.BlockNumber, &receipt.BlockHash, &txIndex) + res.Transactions = append(res.Transactions, TransactionOrHash{Tx: rpcTx}) + } else { + h := tx.Hash() + res.Transactions = append(res.Transactions, TransactionOrHash{Hash: &h}) + } + } + + return res +} + +// TransactionOrHash for union type of transaction and types.Hash +type TransactionOrHash struct { + Hash *common.Hash + Tx *Transaction +} + +// MarshalJSON marshals into json +func (b TransactionOrHash) MarshalJSON() ([]byte, error) { + if b.Hash != nil { + return json.Marshal(b.Hash) + } + return json.Marshal(b.Tx) +} + +// UnmarshalJSON unmarshals from json +func (b *TransactionOrHash) UnmarshalJSON(input []byte) error { + v := string(input) + if strings.HasPrefix(v, "0x") || strings.HasPrefix(v, "\"0x") { + var h common.Hash + err := json.Unmarshal(input, &h) + if err != nil { + return err + } + *b = TransactionOrHash{Hash: &h} + return nil + } + + var t Transaction + err := json.Unmarshal(input, &t) + if err != nil { + return err + } + *b = TransactionOrHash{Tx: &t} + return nil +} + +// Transaction structure +type Transaction struct { + Nonce ArgUint64 `json:"nonce"` + GasPrice ArgBig `json:"gasPrice"` + Gas ArgUint64 `json:"gas"` + To *common.Address `json:"to"` + Value ArgBig `json:"value"` + Input ArgBytes `json:"input"` + V ArgBig `json:"v"` + R ArgBig `json:"r"` + S ArgBig `json:"s"` + Hash common.Hash `json:"hash"` + From common.Address `json:"from"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber *ArgUint64 `json:"blockNumber"` + TxIndex *ArgUint64 `json:"transactionIndex"` + ChainID ArgBig `json:"chainId"` + Type ArgUint64 `json:"type"` +} + +// CoreTx returns a geth core type Transaction +func (t Transaction) CoreTx() *types.Transaction { + return types.NewTx(&types.LegacyTx{ + Nonce: uint64(t.Nonce), + GasPrice: (*big.Int)(&t.GasPrice), + Gas: uint64(t.Gas), + To: t.To, + Value: (*big.Int)(&t.Value), + Data: t.Input, + V: (*big.Int)(&t.V), + R: (*big.Int)(&t.R), + S: (*big.Int)(&t.S), + }) +} + +// NewTransaction creates a transaction instance +func NewTransaction( + t types.Transaction, + blockNumber *big.Int, + blockHash *common.Hash, + txIndex *uint64, +) *Transaction { + v, r, s := t.RawSignatureValues() + + from, _ := state.GetSender(t) + + res := &Transaction{ + Nonce: ArgUint64(t.Nonce()), + GasPrice: ArgBig(*t.GasPrice()), + Gas: ArgUint64(t.Gas()), + To: t.To(), + Value: ArgBig(*t.Value()), + Input: t.Data(), + V: ArgBig(*v), + R: ArgBig(*r), + S: ArgBig(*s), + Hash: t.Hash(), + From: from, + ChainID: ArgBig(*t.ChainId()), + Type: ArgUint64(t.Type()), + } + + if blockNumber != nil { + bn := ArgUint64(blockNumber.Uint64()) + res.BlockNumber = &bn + } + + res.BlockHash = blockHash + + if txIndex != nil { + ti := ArgUint64(*txIndex) + res.TxIndex = &ti + } + + return res +} + +// Receipt structure +type Receipt struct { + Root common.Hash `json:"root"` + CumulativeGasUsed ArgUint64 `json:"cumulativeGasUsed"` + LogsBloom types.Bloom `json:"logsBloom"` + Logs []*types.Log `json:"logs"` + Status ArgUint64 `json:"status"` + TxHash common.Hash `json:"transactionHash"` + TxIndex ArgUint64 `json:"transactionIndex"` + BlockHash common.Hash `json:"blockHash"` + BlockNumber ArgUint64 `json:"blockNumber"` + GasUsed ArgUint64 `json:"gasUsed"` + FromAddr common.Address `json:"from"` + ToAddr *common.Address `json:"to"` + ContractAddress *common.Address `json:"contractAddress"` + Type ArgUint64 `json:"type"` +} + +// NewReceipt creates a new Receipt instance +func NewReceipt(tx types.Transaction, r *types.Receipt) (Receipt, error) { + to := tx.To() + logs := r.Logs + if logs == nil { + logs = []*types.Log{} + } + + var contractAddress *common.Address + if r.ContractAddress != state.ZeroAddress { + ca := r.ContractAddress + contractAddress = &ca + } + + blockNumber := ArgUint64(0) + if r.BlockNumber != nil { + blockNumber = ArgUint64(r.BlockNumber.Uint64()) + } + + from, err := state.GetSender(tx) + if err != nil { + return Receipt{}, err + } + + return Receipt{ + Root: common.BytesToHash(r.PostState), + CumulativeGasUsed: ArgUint64(r.CumulativeGasUsed), + LogsBloom: r.Bloom, + Logs: logs, + Status: ArgUint64(r.Status), + TxHash: r.TxHash, + TxIndex: ArgUint64(r.TransactionIndex), + BlockHash: r.BlockHash, + BlockNumber: blockNumber, + GasUsed: ArgUint64(r.GasUsed), + ContractAddress: contractAddress, + FromAddr: from, + ToAddr: to, + Type: ArgUint64(r.Type), + }, nil +} + +// Log structure +type Log struct { + Address common.Address `json:"address"` + Topics []common.Hash `json:"topics"` + Data ArgBytes `json:"data"` + BlockNumber ArgUint64 `json:"blockNumber"` + TxHash common.Hash `json:"transactionHash"` + TxIndex ArgUint64 `json:"transactionIndex"` + BlockHash common.Hash `json:"blockHash"` + LogIndex ArgUint64 `json:"logIndex"` + Removed bool `json:"removed"` +} + +// NewLog creates a new instance of Log +func NewLog(l types.Log) Log { + return Log{ + Address: l.Address, + Topics: l.Topics, + Data: l.Data, + BlockNumber: ArgUint64(l.BlockNumber), + TxHash: l.TxHash, + TxIndex: ArgUint64(l.TxIndex), + BlockHash: l.BlockHash, + LogIndex: ArgUint64(l.Index), + Removed: l.Removed, + } +} + +// ToBatchNumArg converts a big.Int into a batch number rpc parameter +func ToBatchNumArg(number *big.Int) string { + if number == nil { + return Latest + } + pending := big.NewInt(-1) + if number.Cmp(pending) == 0 { + return Pending + } + return hex.EncodeBig(number) +} diff --git a/jsonrpc/types/types_test.go b/jsonrpc/types/types_test.go new file mode 100644 index 0000000000..29fa459a13 --- /dev/null +++ b/jsonrpc/types/types_test.go @@ -0,0 +1,239 @@ +package types + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestArgHashUnmarshalFromShortString(t *testing.T) { + type testCase struct { + name string + input string + expectedResult string + expectedError error + } + testCases := []testCase{ + { + name: "valid hex value starting with 0x", + input: "0x1", + expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000001", + expectedError: nil, + }, + { + name: "valid hex value starting without 0x", + input: "1", + expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000001", + expectedError: nil, + }, + { + name: "valid full hash value", + input: "0x05b21ee5f65c28a0af8e71290fc33625a1279a8b3d6357ce3ca60f22dbf59e63", + expectedResult: "0x05b21ee5f65c28a0af8e71290fc33625a1279a8b3d6357ce3ca60f22dbf59e63", + expectedError: nil, + }, + { + name: "invalid hex value starting with 0x", + input: "0xG", + expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000000", + expectedError: fmt.Errorf("invalid hash, it needs to be a hexadecimal value"), + }, + { + name: "invalid hex value starting without 0x", + input: "G", + expectedResult: "0x0000000000000000000000000000000000000000000000000000000000000000", + expectedError: fmt.Errorf("invalid hash, it needs to be a hexadecimal value"), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + arg := ArgHash{} + err := arg.UnmarshalText([]byte(testCase.input)) + require.Equal(t, testCase.expectedError, err) + assert.Equal(t, testCase.expectedResult, arg.Hash().String()) + }) + } +} + +func TestArgAddressUnmarshalFromShortString(t *testing.T) { + type testCase struct { + name string + input string + expectedResult string + expectedError error + } + testCases := []testCase{ + { + name: "valid hex value starting with 0x", + input: "0x1", + expectedResult: "0x0000000000000000000000000000000000000001", + expectedError: nil, + }, + { + name: "valid hex value starting without 0x", + input: "1", + expectedResult: "0x0000000000000000000000000000000000000001", + expectedError: nil, + }, + { + name: "valid full address value", + input: "0x748964F22eFd023eB78A246A7AC2506e84CC4545", + expectedResult: "0x748964F22eFd023eB78A246A7AC2506e84CC4545", + expectedError: nil, + }, + { + name: "invalid hex value starting with 0x", + input: "0xG", + expectedResult: "0x0000000000000000000000000000000000000000", + expectedError: fmt.Errorf("invalid address, it needs to be a hexadecimal value"), + }, + { + name: "invalid hex value starting without 0x", + input: "G", + expectedResult: "0x0000000000000000000000000000000000000000", + expectedError: fmt.Errorf("invalid address, it needs to be a hexadecimal value"), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + arg := ArgAddress{} + err := arg.UnmarshalText([]byte(testCase.input)) + require.Equal(t, testCase.expectedError, err) + assert.Equal(t, testCase.expectedResult, arg.Address().String()) + }) + } +} + +func TestBatchUnmarshal(t *testing.T) { + // json: `{"number":"0x1","coinbase":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","stateRoot":"0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72","globalExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000001","localExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000002","accInputHash":"0x0000000000000000000000000000000000000000000000000000000000000003","timestamp":"0x64133495","sendSequencesTxHash":"0x0000000000000000000000000000000000000000000000000000000000000004","verifyBatchTxHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactions":[{"nonce":"0x8","gasPrice":"0x3b9aca00","gas":"0x5208","to":"0xb48ca794d49eec406a5dd2c547717e37b5952a83","value":"0xde0b6b3a7640000","input":"0x","v":"0x7f5","r":"0x27d94abdecca8324d23221cec81f0a3398d7eee2dc831f698fe12447695897d5","s":"0x1b9f1d7cabbb69d309f9e6ffe10b3e205ad86af1058f4dbacdd06a8db03a5669","hash":"0xd0433908a0b56ec6d90758abfe5ae11185e13bedb3d70e8ab7c0d7e3f0e395b5","from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","blockHash":"0x7e8efeb2b5bb9aaef68a9b2f5b6c0a14900745380a68f72f9c15f978546109cc","blockNumber":"0x1","transactionIndex":"0x0","chainId":"0x3e9","type":"0x0"}]}` + type testCase struct { + name string + json string + expected Batch + } + testCases := []testCase{ + { + name: "with out txs", + json: `{"number":"0x1","coinbase":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","stateRoot":"0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72","globalExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000001","localExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000002","accInputHash":"0x0000000000000000000000000000000000000000000000000000000000000003","timestamp":"0x64133495","sendSequencesTxHash":"0x0000000000000000000000000000000000000000000000000000000000000004","verifyBatchTxHash":"0x0000000000000000000000000000000000000000000000000000000000000005"}`, + expected: Batch{ + Number: 1, + Coinbase: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), + StateRoot: common.HexToHash("0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72"), + GlobalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), + LocalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000002"), + AccInputHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000003"), + Timestamp: ArgUint64(1678980245), + SendSequencesTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000004"), + VerifyBatchTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000005"), + }, + }, + { + name: "with txs", + json: `{"number":"0x1","coinbase":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","stateRoot":"0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72","globalExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000001","localExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000002","accInputHash":"0x0000000000000000000000000000000000000000000000000000000000000003","timestamp":"0x64133495","sendSequencesTxHash":"0x0000000000000000000000000000000000000000000000000000000000000004","verifyBatchTxHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactions":[{"nonce":"0x8","gasPrice":"0x3b9aca00","gas":"0x5208","to":"0xb48ca794d49eec406a5dd2c547717e37b5952a83","value":"0xde0b6b3a7640000","input":"0x","v":"0x7f5","r":"0x27d94abdecca8324d23221cec81f0a3398d7eee2dc831f698fe12447695897d5","s":"0x1b9f1d7cabbb69d309f9e6ffe10b3e205ad86af1058f4dbacdd06a8db03a5669","hash":"0xd0433908a0b56ec6d90758abfe5ae11185e13bedb3d70e8ab7c0d7e3f0e395b5","from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","blockHash":"0x7e8efeb2b5bb9aaef68a9b2f5b6c0a14900745380a68f72f9c15f978546109cc","blockNumber":"0x1","transactionIndex":"0x0","chainId":"0x3e9","type":"0x0"}]}`, + expected: Batch{ + Number: 1, + Coinbase: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), + StateRoot: common.HexToHash("0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72"), + GlobalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), + LocalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000002"), + AccInputHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000003"), + Timestamp: ArgUint64(hex.DecodeUint64("0x64133495")), + SendSequencesTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000004"), + VerifyBatchTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000005"), + Transactions: []TransactionOrHash{ + { + Tx: &Transaction{ + Nonce: ArgUint64(hex.DecodeUint64("0x8")), + GasPrice: ArgBig(*hex.DecodeBig("0x3b9aca00")), + Gas: ArgUint64(hex.DecodeUint64("0x5208")), + To: state.HexToAddressPtr("0xb48ca794d49eec406a5dd2c547717e37b5952a83"), + Value: ArgBig(*hex.DecodeBig("0xde0b6b3a7640000")), + Input: ArgBytes{}, + V: ArgBig(*hex.DecodeBig("0x7f5")), + R: ArgBig(*hex.DecodeBig("0x27d94abdecca8324d23221cec81f0a3398d7eee2dc831f698fe12447695897d5")), + S: ArgBig(*hex.DecodeBig("0x1b9f1d7cabbb69d309f9e6ffe10b3e205ad86af1058f4dbacdd06a8db03a5669")), + Hash: common.HexToHash("0xd0433908a0b56ec6d90758abfe5ae11185e13bedb3d70e8ab7c0d7e3f0e395b5"), + From: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), + BlockHash: state.HexToHashPtr("0x7e8efeb2b5bb9aaef68a9b2f5b6c0a14900745380a68f72f9c15f978546109cc"), + BlockNumber: ArgUint64Ptr(ArgUint64(hex.DecodeUint64("0x1"))), + TxIndex: ArgUint64Ptr(ArgUint64(hex.DecodeUint64("0x0"))), + ChainID: ArgBig(*hex.DecodeBig("0x3e9")), + Type: ArgUint64(hex.DecodeUint64("0x0")), + }, + }, + }, + }, + }, + { + name: "with tx hashes", + json: `{"number":"0x1","coinbase":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","stateRoot":"0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72","globalExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000001","localExitRoot":"0x0000000000000000000000000000000000000000000000000000000000000002","accInputHash":"0x0000000000000000000000000000000000000000000000000000000000000003","timestamp":"0x64133495","sendSequencesTxHash":"0x0000000000000000000000000000000000000000000000000000000000000004","verifyBatchTxHash":"0x0000000000000000000000000000000000000000000000000000000000000005","transactions":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002"]}`, + expected: Batch{ + Number: 1, + Coinbase: common.HexToAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"), + StateRoot: common.HexToHash("0x49e7b7eb6bb34b07a1063cd2c7a9cac88845c1867e8a026d69fc00b862c2ca72"), + GlobalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), + LocalExitRoot: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000002"), + AccInputHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000003"), + Timestamp: ArgUint64(1678980245), + SendSequencesTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000004"), + VerifyBatchTxHash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000005"), + Transactions: []TransactionOrHash{ + {Hash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000001")}, + {Hash: state.HexToHashPtr("0x0000000000000000000000000000000000000000000000000000000000000002")}, + }, + }, + }, + } + + for _, testCase := range testCases { + b := []byte(testCase.json) + var result *Batch + err := json.Unmarshal(b, &result) + require.NoError(t, err) + + assert.Equal(t, testCase.expected.Number, result.Number) + assert.Equal(t, testCase.expected.Coinbase, result.Coinbase) + assert.Equal(t, testCase.expected.StateRoot, result.StateRoot) + assert.Equal(t, testCase.expected.GlobalExitRoot, result.GlobalExitRoot) + assert.Equal(t, testCase.expected.LocalExitRoot, result.LocalExitRoot) + assert.Equal(t, testCase.expected.AccInputHash, result.AccInputHash) + assert.Equal(t, testCase.expected.Timestamp, result.Timestamp) + assert.Equal(t, testCase.expected.SendSequencesTxHash, result.SendSequencesTxHash) + assert.Equal(t, testCase.expected.VerifyBatchTxHash, result.VerifyBatchTxHash) + assert.Equal(t, len(testCase.expected.Transactions), len(result.Transactions)) + + for i := 0; i < len(testCase.expected.Transactions); i++ { + txOrHashExpected := testCase.expected.Transactions[i] + txOrHashResult := result.Transactions[i] + + if txOrHashExpected.Hash != nil { + assert.Equal(t, txOrHashExpected.Hash.String(), txOrHashResult.Hash.String()) + } else { + assert.Equal(t, txOrHashExpected.Tx.Nonce, txOrHashResult.Tx.Nonce) + assert.Equal(t, txOrHashExpected.Tx.GasPrice, txOrHashResult.Tx.GasPrice) + assert.Equal(t, txOrHashExpected.Tx.Gas, txOrHashResult.Tx.Gas) + assert.Equal(t, txOrHashExpected.Tx.To, txOrHashResult.Tx.To) + assert.Equal(t, txOrHashExpected.Tx.Value, txOrHashResult.Tx.Value) + assert.Equal(t, txOrHashExpected.Tx.Input, txOrHashResult.Tx.Input) + assert.Equal(t, txOrHashExpected.Tx.V, txOrHashResult.Tx.V) + assert.Equal(t, txOrHashExpected.Tx.R, txOrHashResult.Tx.R) + assert.Equal(t, txOrHashExpected.Tx.S, txOrHashResult.Tx.S) + assert.Equal(t, txOrHashExpected.Tx.Hash, txOrHashResult.Tx.Hash) + assert.Equal(t, txOrHashExpected.Tx.From, txOrHashResult.Tx.From) + assert.Equal(t, txOrHashExpected.Tx.BlockHash, txOrHashResult.Tx.BlockHash) + assert.Equal(t, txOrHashExpected.Tx.BlockNumber, txOrHashResult.Tx.BlockNumber) + assert.Equal(t, txOrHashExpected.Tx.TxIndex, txOrHashResult.Tx.TxIndex) + assert.Equal(t, txOrHashExpected.Tx.ChainID, txOrHashResult.Tx.ChainID) + assert.Equal(t, txOrHashExpected.Tx.Type, txOrHashResult.Tx.Type) + } + } + } +} diff --git a/jsonrpc/web3.go b/jsonrpc/web3.go deleted file mode 100644 index 5867679569..0000000000 --- a/jsonrpc/web3.go +++ /dev/null @@ -1,22 +0,0 @@ -package jsonrpc - -import ( - "math/big" - - "github.com/iden3/go-iden3-crypto/keccak256" -) - -// Web3 contains implementations for the "web3" RPC endpoints -type Web3 struct { -} - -// ClientVersion returns the client version. -func (w *Web3) ClientVersion() (interface{}, rpcError) { - return "Polygon Hermez zkEVM/v2.0.0", nil -} - -// Sha3 returns the keccak256 hash of the given data. -func (w *Web3) Sha3(data argBig) (interface{}, rpcError) { - b := (*big.Int)(&data) - return argBytes(keccak256.Hash(b.Bytes())), nil -} diff --git a/jsonrpc/zkevm.go b/jsonrpc/zkevm.go deleted file mode 100644 index 80bafb3287..0000000000 --- a/jsonrpc/zkevm.go +++ /dev/null @@ -1,64 +0,0 @@ -package jsonrpc - -import ( - "context" - - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/jackc/pgx/v4" -) - -// ZKEVM contains implementations for the "zkevm" RPC endpoints -type ZKEVM struct { - config Config - state stateInterface - txMan dbTxManager -} - -// ConsolidatedBlockNumber returns current block number for consolidated blocks -func (h *ZKEVM) ConsolidatedBlockNumber() (interface{}, rpcError) { - return h.txMan.NewDbTxScope(h.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - lastBlockNumber, err := h.state.GetLastConsolidatedL2BlockNumber(ctx, dbTx) - if err != nil { - const errorMessage = "failed to get last consolidated block number from state" - log.Errorf("%v:%v", errorMessage, err) - return nil, newRPCError(defaultErrorCode, errorMessage) - } - - return hex.EncodeUint64(lastBlockNumber), nil - }) -} - -// IsL2BlockConsolidated returns the consolidation status of a provided block number -func (h *ZKEVM) IsL2BlockConsolidated(blockNumber int) (interface{}, rpcError) { - return h.txMan.NewDbTxScope(h.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - IsL2BlockConsolidated, err := h.state.IsL2BlockConsolidated(ctx, blockNumber, dbTx) - if err != nil { - const errorMessage = "failed to check if the block is consolidated" - log.Errorf("%v:%v", errorMessage, err) - return nil, newRPCError(defaultErrorCode, errorMessage) - } - - return IsL2BlockConsolidated, nil - }) -} - -// IsL2BlockVirtualized returns the virtualisation status of a provided block number -func (h *ZKEVM) IsL2BlockVirtualized(blockNumber int) (interface{}, rpcError) { - return h.txMan.NewDbTxScope(h.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, rpcError) { - IsL2BlockVirtualized, err := h.state.IsL2BlockVirtualized(ctx, blockNumber, dbTx) - if err != nil { - const errorMessage = "failed to check if the block is virtualized" - log.Errorf("%v:%v", errorMessage, err) - return nil, newRPCError(defaultErrorCode, errorMessage) - } - - return IsL2BlockVirtualized, nil - }) -} - -// GetBroadcastURI returns the IP:PORT of the broadcast service provided -// by the Trusted Sequencer JSON RPC server -func (h *ZKEVM) GetBroadcastURI() (interface{}, rpcError) { - return h.config.BroadcastURI, nil -} diff --git a/jsonrpc/zkevm_test.go b/jsonrpc/zkevm_test.go deleted file mode 100644 index 266bb2906b..0000000000 --- a/jsonrpc/zkevm_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package jsonrpc - -import ( - "context" - "encoding/json" - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestConsolidatedBlockNumber(t *testing.T) { - s, m, _ := newSequencerMockedServer(t) - defer s.Stop() - - type testCase struct { - Name string - ExpectedResult *uint64 - ExpectedError rpcError - SetupMocks func(m *mocks) - } - - testCases := []testCase{ - { - Name: "Get consolidated block number successfully", - ExpectedResult: ptrUint64(10), - SetupMocks: func(m *mocks) { - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("GetLastConsolidatedL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(10), nil). - Once() - }, - }, - { - Name: "failed to get consolidated block number", - ExpectedResult: nil, - ExpectedError: newRPCError(defaultErrorCode, "failed to get last consolidated block number from state"), - SetupMocks: func(m *mocks) { - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("GetLastConsolidatedL2BlockNumber", context.Background(), m.DbTx). - Return(uint64(0), errors.New("failed to get last consolidated block number")). - Once() - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - tc := testCase - tc.SetupMocks(m) - - res, err := s.JSONRPCCall("zkevm_consolidatedBlockNumber") - require.NoError(t, err) - - if res.Result != nil { - var result argUint64 - err = json.Unmarshal(res.Result, &result) - require.NoError(t, err) - assert.Equal(t, *tc.ExpectedResult, uint64(result)) - } - - if res.Error != nil || tc.ExpectedError != nil { - assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) - assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) - } - }) - } -} - -func TestIsL2BlockConsolidated(t *testing.T) { - s, m, _ := newSequencerMockedServer(t) - defer s.Stop() - - type testCase struct { - Name string - ExpectedResult bool - ExpectedError rpcError - SetupMocks func(m *mocks) - } - - testCases := []testCase{ - { - Name: "Query status of block number successfully", - ExpectedResult: true, - SetupMocks: func(m *mocks) { - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("IsL2BlockConsolidated", context.Background(), 1, m.DbTx). - Return(true, nil). - Once() - }, - }, - { - Name: "Failed to query the consolidation status", - ExpectedResult: false, - ExpectedError: newRPCError(defaultErrorCode, "failed to check if the block is consolidated"), - SetupMocks: func(m *mocks) { - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("IsL2BlockConsolidated", context.Background(), 1, m.DbTx). - Return(true, errors.New("failed to check if the block is consolidated")). - Once() - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - tc := testCase - tc.SetupMocks(m) - - res, err := s.JSONRPCCall("zkevm_isL2BlockConsolidated", 1) - require.NoError(t, err) - - if res.Result != nil { - var result bool - err = json.Unmarshal(res.Result, &result) - require.NoError(t, err) - assert.Equal(t, tc.ExpectedResult, result) - } - - if res.Error != nil || tc.ExpectedError != nil { - assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) - assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) - } - }) - } -} - -func TestIsL2BlockVirtualized(t *testing.T) { - s, m, _ := newSequencerMockedServer(t) - defer s.Stop() - - type testCase struct { - Name string - ExpectedResult bool - ExpectedError rpcError - SetupMocks func(m *mocks) - } - - testCases := []testCase{ - { - Name: "Query status of block number successfully", - ExpectedResult: true, - SetupMocks: func(m *mocks) { - m.DbTx. - On("Commit", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("IsL2BlockVirtualized", context.Background(), 1, m.DbTx). - Return(true, nil). - Once() - }, - }, - { - Name: "Failed to query the virtualization status", - ExpectedResult: false, - ExpectedError: newRPCError(defaultErrorCode, "failed to check if the block is virtualized"), - SetupMocks: func(m *mocks) { - m.DbTx. - On("Rollback", context.Background()). - Return(nil). - Once() - - m.State. - On("BeginStateTransaction", context.Background()). - Return(m.DbTx, nil). - Once() - - m.State. - On("IsL2BlockVirtualized", context.Background(), 1, m.DbTx). - Return(true, errors.New("failed to check if the block is virtualized")). - Once() - }, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - tc := testCase - tc.SetupMocks(m) - - res, err := s.JSONRPCCall("zkevm_isL2BlockVirtualized", 1) - require.NoError(t, err) - - if res.Result != nil { - var result bool - err = json.Unmarshal(res.Result, &result) - require.NoError(t, err) - assert.Equal(t, tc.ExpectedResult, result) - } - - if res.Error != nil || tc.ExpectedError != nil { - assert.Equal(t, tc.ExpectedError.ErrorCode(), res.Error.Code) - assert.Equal(t, tc.ExpectedError.Error(), res.Error.Message) - } - }) - } -} - -func ptrUint64(n uint64) *uint64 { - return &n -} diff --git a/log/config.go b/log/config.go index 697f6d8e9d..7cee754ad0 100644 --- a/log/config.go +++ b/log/config.go @@ -2,6 +2,8 @@ package log // Config for log type Config struct { + // Environment defining the log format ("production" or "development"). + Environment LogEnvironment `mapstructure:"Environment"` // Level of log, e.g. INFO, WARN, ... Level string `mapstructure:"Level"` // Outputs diff --git a/log/log.go b/log/log.go index cacecef536..f8d26d08a4 100644 --- a/log/log.go +++ b/log/log.go @@ -2,26 +2,47 @@ package log import ( "fmt" + "os" "strings" - "time" + "github.com/0xPolygonHermez/zkevm-node" "github.com/hermeznetwork/tracerr" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) -var log *zap.SugaredLogger +// LogEnvironment represents the possible log environments. +type LogEnvironment string -func getDefaultLog() *zap.SugaredLogger { - var err error +const ( + // EnvironmentProduction production log environment. + EnvironmentProduction = LogEnvironment("production") + // EnvironmentDevelopment development log environment. + EnvironmentDevelopment = LogEnvironment("development") +) + +// Logger is a wrapper providing logging facilities. +type Logger struct { + x *zap.SugaredLogger +} + +// root logger +var log *Logger + +func getDefaultLog() *Logger { if log != nil { return log } // default level: debug - log, _, err = NewLogger(Config{"debug", []string{"stdout"}}) + zapLogger, _, err := NewLogger(Config{ + Environment: EnvironmentDevelopment, + Level: "debug", + Outputs: []string{"stderr"}, + }) if err != nil { panic(err) } + log = &Logger{x: zapLogger} return log } @@ -31,11 +52,11 @@ func getDefaultLog() *zap.SugaredLogger { // should be added at the outputs array. To avoid printing the logs but storing // them on a file, can use []string{"pathtofile.log"} func Init(cfg Config) { - var err error - log, _, err = NewLogger(cfg) + zapLogger, _, err := NewLogger(cfg) if err != nil { panic(err) } + log = &Logger{x: zapLogger} } // NewLogger creates the logger with defined level. outputs defines the outputs where the @@ -50,30 +71,20 @@ func NewLogger(cfg Config) (*zap.SugaredLogger, *zap.AtomicLevel, error) { return nil, nil, fmt.Errorf("error on setting log level: %s", err) } - zapCfg := zap.Config{ - Level: level, - Encoding: "console", - OutputPaths: cfg.Outputs, - ErrorOutputPaths: []string{"stderr"}, - EncoderConfig: zapcore.EncoderConfig{ - MessageKey: "message", - - LevelKey: "level", - EncodeLevel: zapcore.CapitalColorLevelEncoder, - - TimeKey: "timestamp", - EncodeTime: func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { - encoder.AppendString(ts.Local().Format(time.RFC3339)) - }, - EncodeDuration: zapcore.SecondsDurationEncoder, - - CallerKey: "caller", - EncodeCaller: zapcore.ShortCallerEncoder, - - // StacktraceKey: "stacktrace", - StacktraceKey: "", - LineEnding: zapcore.DefaultLineEnding, - }, + var zapCfg zap.Config + + switch cfg.Environment { + case EnvironmentProduction: + zapCfg = zap.NewProductionConfig() + default: + zapCfg = zap.NewDevelopmentConfig() + zapCfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder + } + zapCfg.Level = level + zapCfg.OutputPaths = cfg.Outputs + zapCfg.InitialFields = map[string]interface{}{ + "version": zkevm.Version, + "pid": os.Getpid(), } logger, err := zapCfg.Build() @@ -81,10 +92,33 @@ func NewLogger(cfg Config) (*zap.SugaredLogger, *zap.AtomicLevel, error) { return nil, nil, err } defer logger.Sync() //nolint:gosec,errcheck - withOptions := logger.WithOptions(zap.AddCallerSkip(1)) + + // skip 2 callers: one for our wrapper methods and one for the package functions + withOptions := logger.WithOptions(zap.AddCallerSkip(2)) //nolint:gomnd return withOptions.Sugar(), &level, nil } +// WithFields returns a new Logger (derived from the root one) with additional +// fields as per keyValuePairs. The root Logger instance is not affected. +func WithFields(keyValuePairs ...interface{}) *Logger { + l := getDefaultLog().WithFields(keyValuePairs...) + + // since we are returning a new instance, remove one caller from the + // stack, because we'll be calling the retruned Logger methods + // directly, not the package functions. + x := l.x.WithOptions(zap.AddCallerSkip(-1)) + l.x = x + return l +} + +// WithFields returns a new Logger with additional fields as per keyValuePairs. +// The original Logger instance is not affected. +func (l *Logger) WithFields(keyValuePairs ...interface{}) *Logger { + return &Logger{ + x: l.x.With(keyValuePairs...), + } +} + func sprintStackTrace(st []tracerr.Frame) string { builder := strings.Builder{} // Skip deepest frame because it belongs to the go runtime and we don't @@ -112,57 +146,108 @@ func appendStackTraceMaybeArgs(args []interface{}) []interface{} { } // Debug calls log.Debug +func (l *Logger) Debug(args ...interface{}) { + l.x.Debug(args...) +} + +// Info calls log.Info +func (l *Logger) Info(args ...interface{}) { + l.x.Info(args...) +} + +// Warn calls log.Warn +func (l *Logger) Warn(args ...interface{}) { + l.x.Warn(args...) +} + +// Error calls log.Error +func (l *Logger) Error(args ...interface{}) { + l.x.Error(args...) +} + +// Fatal calls log.Fatal +func (l *Logger) Fatal(args ...interface{}) { + l.x.Fatal(args...) +} + +// Debugf calls log.Debugf +func (l *Logger) Debugf(template string, args ...interface{}) { + l.x.Debugf(template, args...) +} + +// Infof calls log.Infof +func (l *Logger) Infof(template string, args ...interface{}) { + l.x.Infof(template, args...) +} + +// Warnf calls log.Warnf +func (l *Logger) Warnf(template string, args ...interface{}) { + l.x.Warnf(template, args...) +} + +// Fatalf calls log.Fatalf +func (l *Logger) Fatalf(template string, args ...interface{}) { + l.x.Fatalf(template, args...) +} + +// Errorf calls log.Errorf and stores the error message into the ErrorFile +func (l *Logger) Errorf(template string, args ...interface{}) { + l.x.Errorf(template, args...) +} + +// Debug calls log.Debug on the root Logger. func Debug(args ...interface{}) { getDefaultLog().Debug(args...) } -// Info calls log.Info +// Info calls log.Info on the root Logger. func Info(args ...interface{}) { getDefaultLog().Info(args...) } -// Warn calls log.Warn +// Warn calls log.Warn on the root Logger. func Warn(args ...interface{}) { getDefaultLog().Warn(args...) } -// Error calls log.Error +// Error calls log.Error on the root Logger. func Error(args ...interface{}) { args = appendStackTraceMaybeArgs(args) getDefaultLog().Error(args...) } -// Fatal calls log.Fatal +// Fatal calls log.Fatal on the root Logger. func Fatal(args ...interface{}) { args = appendStackTraceMaybeArgs(args) getDefaultLog().Fatal(args...) } -// Debugf calls log.Debugf +// Debugf calls log.Debugf on the root Logger. func Debugf(template string, args ...interface{}) { getDefaultLog().Debugf(template, args...) } -// Infof calls log.Infof +// Infof calls log.Infof on the root Logger. func Infof(template string, args ...interface{}) { getDefaultLog().Infof(template, args...) } -// Warnf calls log.Warnf +// Warnf calls log.Warnf on the root Logger. func Warnf(template string, args ...interface{}) { getDefaultLog().Warnf(template, args...) } -// Fatalf calls log.Fatalf +// Fatalf calls log.Fatalf on the root Logger. func Fatalf(template string, args ...interface{}) { args = appendStackTraceMaybeArgs(args) - getDefaultLog().Fatalf(template, args...) + getDefaultLog().Fatalf(template+" %s", args...) } -// Errorf calls log.Errorf and stores the error message into the ErrorFile +// Errorf calls log.Errorf on the root logger and stores the error message into +// the ErrorFile. func Errorf(template string, args ...interface{}) { args = appendStackTraceMaybeArgs(args) - getDefaultLog().Errorf(template, args...) + getDefaultLog().Errorf(template+" %s", args...) } // appendStackTraceMaybeKV will append the stacktrace to the KV @@ -181,28 +266,53 @@ func appendStackTraceMaybeKV(msg string, kv []interface{}) string { } // Debugw calls log.Debugw -func Debugw(template string, kv ...interface{}) { - getDefaultLog().Debugw(template, kv...) +func (l *Logger) Debugw(msg string, kv ...interface{}) { + l.x.Debugw(msg, kv...) } // Infow calls log.Infow -func Infow(template string, kv ...interface{}) { - getDefaultLog().Infow(template, kv...) +func (l *Logger) Infow(msg string, kv ...interface{}) { + l.x.Infow(msg, kv...) } // Warnw calls log.Warnw -func Warnw(template string, kv ...interface{}) { - getDefaultLog().Warnw(template, kv...) +func (l *Logger) Warnw(msg string, kv ...interface{}) { + l.x.Warnw(msg, kv...) } // Errorw calls log.Errorw -func Errorw(template string, kv ...interface{}) { - template = appendStackTraceMaybeKV(template, kv) - getDefaultLog().Errorw(template, kv...) +func (l *Logger) Errorw(msg string, kv ...interface{}) { + l.x.Errorw(msg, kv...) } // Fatalw calls log.Fatalw -func Fatalw(template string, kv ...interface{}) { - template = appendStackTraceMaybeKV(template, kv) - getDefaultLog().Fatalw(template, kv...) +func (l *Logger) Fatalw(msg string, kv ...interface{}) { + l.x.Fatalw(msg, kv...) +} + +// Debugw calls log.Debugw on the root Logger. +func Debugw(msg string, kv ...interface{}) { + getDefaultLog().Debugw(msg, kv...) +} + +// Infow calls log.Infow on the root Logger. +func Infow(msg string, kv ...interface{}) { + getDefaultLog().Infow(msg, kv...) +} + +// Warnw calls log.Warnw on the root Logger. +func Warnw(msg string, kv ...interface{}) { + getDefaultLog().Warnw(msg, kv...) +} + +// Errorw calls log.Errorw on the root Logger. +func Errorw(msg string, kv ...interface{}) { + msg = appendStackTraceMaybeKV(msg, kv) + getDefaultLog().Errorw(msg, kv...) +} + +// Fatalw calls log.Fatalw on the root Logger. +func Fatalw(msg string, kv ...interface{}) { + msg = appendStackTraceMaybeKV(msg, kv) + getDefaultLog().Fatalw(msg, kv...) } diff --git a/log/log_test.go b/log/log_test.go index 598755db6e..9d33bcd01e 100644 --- a/log/log_test.go +++ b/log/log_test.go @@ -18,8 +18,9 @@ func TestLogNotInitialized(t *testing.T) { func TestLog(t *testing.T) { cfg := Config{ - Level: "debug", - Outputs: []string{"stdout"}, //[]string{"stdout", "test.log"} + Environment: EnvironmentDevelopment, + Level: "debug", + Outputs: []string{"stderr"}, //[]string{"stdout", "test.log"} } Init(cfg) diff --git a/merkletree/pb/statedb.pb.go b/merkletree/pb/statedb.pb.go index d4c625ab93..73b20eb3da 100644 --- a/merkletree/pb/statedb.pb.go +++ b/merkletree/pb/statedb.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v3.21.6 +// protoc v3.21.12 // source: statedb.proto package pb @@ -24,28 +24,31 @@ const ( type ResultCode_Code int32 const ( - ResultCode_CODE_UNSPECIFIED ResultCode_Code = 0 - ResultCode_CODE_SUCCESS ResultCode_Code = 1 - ResultCode_CODE_KEY_NOT_FOUND ResultCode_Code = 2 - ResultCode_CODE_DB_ERROR ResultCode_Code = 3 - ResultCode_CODE_INTERNAL_ERROR ResultCode_Code = 4 + ResultCode_CODE_UNSPECIFIED ResultCode_Code = 0 + ResultCode_CODE_SUCCESS ResultCode_Code = 1 + ResultCode_CODE_DB_KEY_NOT_FOUND ResultCode_Code = 2 // Requested key was not found in database + ResultCode_CODE_DB_ERROR ResultCode_Code = 3 // Error connecting to database, or processing request + ResultCode_CODE_INTERNAL_ERROR ResultCode_Code = 4 + ResultCode_CODE_SMT_INVALID_DATA_SIZE ResultCode_Code = 14 // Invalid size for the data of MT node ) // Enum value maps for ResultCode_Code. var ( ResultCode_Code_name = map[int32]string{ - 0: "CODE_UNSPECIFIED", - 1: "CODE_SUCCESS", - 2: "CODE_KEY_NOT_FOUND", - 3: "CODE_DB_ERROR", - 4: "CODE_INTERNAL_ERROR", + 0: "CODE_UNSPECIFIED", + 1: "CODE_SUCCESS", + 2: "CODE_DB_KEY_NOT_FOUND", + 3: "CODE_DB_ERROR", + 4: "CODE_INTERNAL_ERROR", + 14: "CODE_SMT_INVALID_DATA_SIZE", } ResultCode_Code_value = map[string]int32{ - "CODE_UNSPECIFIED": 0, - "CODE_SUCCESS": 1, - "CODE_KEY_NOT_FOUND": 2, - "CODE_DB_ERROR": 3, - "CODE_INTERNAL_ERROR": 4, + "CODE_UNSPECIFIED": 0, + "CODE_SUCCESS": 1, + "CODE_DB_KEY_NOT_FOUND": 2, + "CODE_DB_ERROR": 3, + "CODE_INTERNAL_ERROR": 4, + "CODE_SMT_INVALID_DATA_SIZE": 14, } ) @@ -73,7 +76,7 @@ func (x ResultCode_Code) Number() protoreflect.EnumNumber { // Deprecated: Use ResultCode_Code.Descriptor instead. func (ResultCode_Code) EnumDescriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{11, 0} + return file_statedb_proto_rawDescGZIP(), []int{15, 0} } type Version struct { @@ -128,18 +131,20 @@ func (x *Version) GetV0_0_1() string { // @param {old_root} - merkle-tree root // @param {key} - key to set // @param {value} - scalar value to set (HEX string format) -// @param {persistent} - indicates if it should be stored in the database (true) or only in the memory cache (false) +// @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) // @param {details} - indicates if it should return all response parameters (true) or just the new root (false) +// @param {get_db_read_log} - indicates if it should return the DB reads generated during the execution of the request type SetRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - OldRoot *Fea `protobuf:"bytes,1,opt,name=old_root,json=oldRoot,proto3" json:"old_root,omitempty"` - Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` - Persistent bool `protobuf:"varint,4,opt,name=persistent,proto3" json:"persistent,omitempty"` - Details bool `protobuf:"varint,5,opt,name=details,proto3" json:"details,omitempty"` + OldRoot *Fea `protobuf:"bytes,1,opt,name=old_root,json=oldRoot,proto3" json:"old_root,omitempty"` + Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` + Persistent bool `protobuf:"varint,4,opt,name=persistent,proto3" json:"persistent,omitempty"` + Details bool `protobuf:"varint,5,opt,name=details,proto3" json:"details,omitempty"` + GetDbReadLog bool `protobuf:"varint,6,opt,name=get_db_read_log,json=getDbReadLog,proto3" json:"get_db_read_log,omitempty"` } func (x *SetRequest) Reset() { @@ -209,19 +214,28 @@ func (x *SetRequest) GetDetails() bool { return false } +func (x *SetRequest) GetGetDbReadLog() bool { + if x != nil { + return x.GetDbReadLog + } + return false +} + //* // @dev GetRequest // @param {root} - merkle-tree root // @param {key} - key to look for // @param {details} - indicates if it should return all response parameters (true) or just the new root (false) +// @param {get_db_read_log} - indicates if it should return the DB reads generated during the execution of the request type GetRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Root *Fea `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty"` - Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Details bool `protobuf:"varint,3,opt,name=details,proto3" json:"details,omitempty"` + Root *Fea `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty"` + Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Details bool `protobuf:"varint,3,opt,name=details,proto3" json:"details,omitempty"` + GetDbReadLog bool `protobuf:"varint,4,opt,name=get_db_read_log,json=getDbReadLog,proto3" json:"get_db_read_log,omitempty"` } func (x *GetRequest) Reset() { @@ -277,11 +291,18 @@ func (x *GetRequest) GetDetails() bool { return false } +func (x *GetRequest) GetGetDbReadLog() bool { + if x != nil { + return x.GetDbReadLog + } + return false +} + //* // @dev SetProgramRequest -// @param {key} - hash to set +// @param {key} - key to set // @param {data} - Program data to store -// @param {persistent} - indicates if it should be stored in the database (true) or only in the memory cache (false) +// @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) type SetProgramRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -347,7 +368,7 @@ func (x *SetProgramRequest) GetPersistent() bool { //* // @dev GetProgramRequest -// @param {key} - hash to get program data +// @param {key} - key to get program data type GetProgramRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -395,6 +416,124 @@ func (x *GetProgramRequest) GetKey() *Fea { return nil } +//* +// @dev LoadDBRequest +// @param {input_db} - list of db records (MT) to load in the database +// @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) +type LoadDBRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InputDb map[string]*FeList `protobuf:"bytes,1,rep,name=input_db,json=inputDb,proto3" json:"input_db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Persistent bool `protobuf:"varint,2,opt,name=persistent,proto3" json:"persistent,omitempty"` +} + +func (x *LoadDBRequest) Reset() { + *x = LoadDBRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_statedb_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoadDBRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoadDBRequest) ProtoMessage() {} + +func (x *LoadDBRequest) ProtoReflect() protoreflect.Message { + mi := &file_statedb_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoadDBRequest.ProtoReflect.Descriptor instead. +func (*LoadDBRequest) Descriptor() ([]byte, []int) { + return file_statedb_proto_rawDescGZIP(), []int{5} +} + +func (x *LoadDBRequest) GetInputDb() map[string]*FeList { + if x != nil { + return x.InputDb + } + return nil +} + +func (x *LoadDBRequest) GetPersistent() bool { + if x != nil { + return x.Persistent + } + return false +} + +//* +// @dev LoadProgramDBRequest +// @param {input_program_db} - list of db records (program) to load in the database +// @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) +type LoadProgramDBRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InputProgramDb map[string][]byte `protobuf:"bytes,1,rep,name=input_program_db,json=inputProgramDb,proto3" json:"input_program_db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Persistent bool `protobuf:"varint,2,opt,name=persistent,proto3" json:"persistent,omitempty"` +} + +func (x *LoadProgramDBRequest) Reset() { + *x = LoadProgramDBRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_statedb_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LoadProgramDBRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LoadProgramDBRequest) ProtoMessage() {} + +func (x *LoadProgramDBRequest) ProtoReflect() protoreflect.Message { + mi := &file_statedb_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LoadProgramDBRequest.ProtoReflect.Descriptor instead. +func (*LoadProgramDBRequest) Descriptor() ([]byte, []int) { + return file_statedb_proto_rawDescGZIP(), []int{6} +} + +func (x *LoadProgramDBRequest) GetInputProgramDb() map[string][]byte { + if x != nil { + return x.InputProgramDb + } + return nil +} + +func (x *LoadProgramDBRequest) GetPersistent() bool { + if x != nil { + return x.Persistent + } + return false +} + //* // @dev SetResponse // @param {old_root} - merkle-tree root @@ -407,29 +546,33 @@ func (x *GetProgramRequest) GetKey() *Fea { // @param {old_value} - old value (HEX string format) // @param {new_value} - new value (HEX string format) // @param {mode} +// @param {proof_hash_counter} +// @param {db_read_log} - list of db records read during the execution of the request // @param {result} - result code type SetResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - OldRoot *Fea `protobuf:"bytes,1,opt,name=old_root,json=oldRoot,proto3" json:"old_root,omitempty"` - NewRoot *Fea `protobuf:"bytes,2,opt,name=new_root,json=newRoot,proto3" json:"new_root,omitempty"` - Key *Fea `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` - Siblings map[uint64]*SiblingList `protobuf:"bytes,4,rep,name=siblings,proto3" json:"siblings,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - InsKey *Fea `protobuf:"bytes,5,opt,name=ins_key,json=insKey,proto3" json:"ins_key,omitempty"` - InsValue string `protobuf:"bytes,6,opt,name=ins_value,json=insValue,proto3" json:"ins_value,omitempty"` - IsOld0 bool `protobuf:"varint,7,opt,name=is_old0,json=isOld0,proto3" json:"is_old0,omitempty"` - OldValue string `protobuf:"bytes,8,opt,name=old_value,json=oldValue,proto3" json:"old_value,omitempty"` - NewValue string `protobuf:"bytes,9,opt,name=new_value,json=newValue,proto3" json:"new_value,omitempty"` - Mode string `protobuf:"bytes,10,opt,name=mode,proto3" json:"mode,omitempty"` - Result *ResultCode `protobuf:"bytes,11,opt,name=result,proto3" json:"result,omitempty"` + OldRoot *Fea `protobuf:"bytes,1,opt,name=old_root,json=oldRoot,proto3" json:"old_root,omitempty"` + NewRoot *Fea `protobuf:"bytes,2,opt,name=new_root,json=newRoot,proto3" json:"new_root,omitempty"` + Key *Fea `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` + Siblings map[uint64]*SiblingList `protobuf:"bytes,4,rep,name=siblings,proto3" json:"siblings,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + InsKey *Fea `protobuf:"bytes,5,opt,name=ins_key,json=insKey,proto3" json:"ins_key,omitempty"` + InsValue string `protobuf:"bytes,6,opt,name=ins_value,json=insValue,proto3" json:"ins_value,omitempty"` + IsOld0 bool `protobuf:"varint,7,opt,name=is_old0,json=isOld0,proto3" json:"is_old0,omitempty"` + OldValue string `protobuf:"bytes,8,opt,name=old_value,json=oldValue,proto3" json:"old_value,omitempty"` + NewValue string `protobuf:"bytes,9,opt,name=new_value,json=newValue,proto3" json:"new_value,omitempty"` + Mode string `protobuf:"bytes,10,opt,name=mode,proto3" json:"mode,omitempty"` + ProofHashCounter uint64 `protobuf:"varint,11,opt,name=proof_hash_counter,json=proofHashCounter,proto3" json:"proof_hash_counter,omitempty"` + DbReadLog map[string]*FeList `protobuf:"bytes,12,rep,name=db_read_log,json=dbReadLog,proto3" json:"db_read_log,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Result *ResultCode `protobuf:"bytes,13,opt,name=result,proto3" json:"result,omitempty"` } func (x *SetResponse) Reset() { *x = SetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[5] + mi := &file_statedb_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -442,7 +585,7 @@ func (x *SetResponse) String() string { func (*SetResponse) ProtoMessage() {} func (x *SetResponse) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[5] + mi := &file_statedb_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -455,7 +598,7 @@ func (x *SetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResponse.ProtoReflect.Descriptor instead. func (*SetResponse) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{5} + return file_statedb_proto_rawDescGZIP(), []int{7} } func (x *SetResponse) GetOldRoot() *Fea { @@ -528,6 +671,20 @@ func (x *SetResponse) GetMode() string { return "" } +func (x *SetResponse) GetProofHashCounter() uint64 { + if x != nil { + return x.ProofHashCounter + } + return 0 +} + +func (x *SetResponse) GetDbReadLog() map[string]*FeList { + if x != nil { + return x.DbReadLog + } + return nil +} + func (x *SetResponse) GetResult() *ResultCode { if x != nil { return x.Result @@ -544,26 +701,30 @@ func (x *SetResponse) GetResult() *ResultCode { // @param {ins_value} - value found (HEX string format) // @param {is_old0} - is new insert or delete // @param {value} - value retrieved (HEX string format) +// @param {proof_hash_counter} +// @param {db_read_log} - list of db records read during the execution of the request // @param {result} - result code type GetResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Root *Fea `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty"` - Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Siblings map[uint64]*SiblingList `protobuf:"bytes,3,rep,name=siblings,proto3" json:"siblings,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - InsKey *Fea `protobuf:"bytes,4,opt,name=ins_key,json=insKey,proto3" json:"ins_key,omitempty"` - InsValue string `protobuf:"bytes,5,opt,name=ins_value,json=insValue,proto3" json:"ins_value,omitempty"` - IsOld0 bool `protobuf:"varint,6,opt,name=is_old0,json=isOld0,proto3" json:"is_old0,omitempty"` - Value string `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` - Result *ResultCode `protobuf:"bytes,8,opt,name=result,proto3" json:"result,omitempty"` + Root *Fea `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty"` + Key *Fea `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Siblings map[uint64]*SiblingList `protobuf:"bytes,3,rep,name=siblings,proto3" json:"siblings,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + InsKey *Fea `protobuf:"bytes,4,opt,name=ins_key,json=insKey,proto3" json:"ins_key,omitempty"` + InsValue string `protobuf:"bytes,5,opt,name=ins_value,json=insValue,proto3" json:"ins_value,omitempty"` + IsOld0 bool `protobuf:"varint,6,opt,name=is_old0,json=isOld0,proto3" json:"is_old0,omitempty"` + Value string `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` + ProofHashCounter uint64 `protobuf:"varint,8,opt,name=proof_hash_counter,json=proofHashCounter,proto3" json:"proof_hash_counter,omitempty"` + DbReadLog map[string]*FeList `protobuf:"bytes,9,rep,name=db_read_log,json=dbReadLog,proto3" json:"db_read_log,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Result *ResultCode `protobuf:"bytes,10,opt,name=result,proto3" json:"result,omitempty"` } func (x *GetResponse) Reset() { *x = GetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[6] + mi := &file_statedb_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -576,7 +737,7 @@ func (x *GetResponse) String() string { func (*GetResponse) ProtoMessage() {} func (x *GetResponse) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[6] + mi := &file_statedb_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -589,7 +750,7 @@ func (x *GetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResponse.ProtoReflect.Descriptor instead. func (*GetResponse) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{6} + return file_statedb_proto_rawDescGZIP(), []int{8} } func (x *GetResponse) GetRoot() *Fea { @@ -641,6 +802,20 @@ func (x *GetResponse) GetValue() string { return "" } +func (x *GetResponse) GetProofHashCounter() uint64 { + if x != nil { + return x.ProofHashCounter + } + return 0 +} + +func (x *GetResponse) GetDbReadLog() map[string]*FeList { + if x != nil { + return x.DbReadLog + } + return nil +} + func (x *GetResponse) GetResult() *ResultCode { if x != nil { return x.Result @@ -662,7 +837,7 @@ type SetProgramResponse struct { func (x *SetProgramResponse) Reset() { *x = SetProgramResponse{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[7] + mi := &file_statedb_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -675,7 +850,7 @@ func (x *SetProgramResponse) String() string { func (*SetProgramResponse) ProtoMessage() {} func (x *SetProgramResponse) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[7] + mi := &file_statedb_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -688,7 +863,7 @@ func (x *SetProgramResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetProgramResponse.ProtoReflect.Descriptor instead. func (*SetProgramResponse) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{7} + return file_statedb_proto_rawDescGZIP(), []int{9} } func (x *SetProgramResponse) GetResult() *ResultCode { @@ -714,7 +889,7 @@ type GetProgramResponse struct { func (x *GetProgramResponse) Reset() { *x = GetProgramResponse{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[8] + mi := &file_statedb_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -727,7 +902,7 @@ func (x *GetProgramResponse) String() string { func (*GetProgramResponse) ProtoMessage() {} func (x *GetProgramResponse) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[8] + mi := &file_statedb_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -740,7 +915,7 @@ func (x *GetProgramResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetProgramResponse.ProtoReflect.Descriptor instead. func (*GetProgramResponse) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{8} + return file_statedb_proto_rawDescGZIP(), []int{10} } func (x *GetProgramResponse) GetData() []byte { @@ -757,6 +932,56 @@ func (x *GetProgramResponse) GetResult() *ResultCode { return nil } +//* +// @dev FlushResponse +// @param {result} - result code +type FlushResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *ResultCode `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (x *FlushResponse) Reset() { + *x = FlushResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_statedb_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlushResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlushResponse) ProtoMessage() {} + +func (x *FlushResponse) ProtoReflect() protoreflect.Message { + mi := &file_statedb_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FlushResponse.ProtoReflect.Descriptor instead. +func (*FlushResponse) Descriptor() ([]byte, []int) { + return file_statedb_proto_rawDescGZIP(), []int{11} +} + +func (x *FlushResponse) GetResult() *ResultCode { + if x != nil { + return x.Result + } + return nil +} + //* // @dev Array of 4 FE // @param {fe0} - Field Element value for pos 0 @@ -777,7 +1002,7 @@ type Fea struct { func (x *Fea) Reset() { *x = Fea{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[9] + mi := &file_statedb_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -790,7 +1015,7 @@ func (x *Fea) String() string { func (*Fea) ProtoMessage() {} func (x *Fea) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[9] + mi := &file_statedb_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -803,7 +1028,7 @@ func (x *Fea) ProtoReflect() protoreflect.Message { // Deprecated: Use Fea.ProtoReflect.Descriptor instead. func (*Fea) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{9} + return file_statedb_proto_rawDescGZIP(), []int{12} } func (x *Fea) GetFe0() uint64 { @@ -834,9 +1059,59 @@ func (x *Fea) GetFe3() uint64 { return 0 } +//* +// @dev FE (Field Element) List +// @param {fe} - list of Fe +type FeList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Fe []uint64 `protobuf:"varint,1,rep,packed,name=fe,proto3" json:"fe,omitempty"` +} + +func (x *FeList) Reset() { + *x = FeList{} + if protoimpl.UnsafeEnabled { + mi := &file_statedb_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FeList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FeList) ProtoMessage() {} + +func (x *FeList) ProtoReflect() protoreflect.Message { + mi := &file_statedb_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FeList.ProtoReflect.Descriptor instead. +func (*FeList) Descriptor() ([]byte, []int) { + return file_statedb_proto_rawDescGZIP(), []int{13} +} + +func (x *FeList) GetFe() []uint64 { + if x != nil { + return x.Fe + } + return nil +} + //* // @dev Siblings List -// @param {sibling} - sibling +// @param {sibling} - list of siblings type SiblingList struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -848,7 +1123,7 @@ type SiblingList struct { func (x *SiblingList) Reset() { *x = SiblingList{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[10] + mi := &file_statedb_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -861,7 +1136,7 @@ func (x *SiblingList) String() string { func (*SiblingList) ProtoMessage() {} func (x *SiblingList) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[10] + mi := &file_statedb_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -874,7 +1149,7 @@ func (x *SiblingList) ProtoReflect() protoreflect.Message { // Deprecated: Use SiblingList.ProtoReflect.Descriptor instead. func (*SiblingList) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{10} + return file_statedb_proto_rawDescGZIP(), []int{14} } func (x *SiblingList) GetSibling() []uint64 { @@ -898,7 +1173,7 @@ type ResultCode struct { func (x *ResultCode) Reset() { *x = ResultCode{} if protoimpl.UnsafeEnabled { - mi := &file_statedb_proto_msgTypes[11] + mi := &file_statedb_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -911,7 +1186,7 @@ func (x *ResultCode) String() string { func (*ResultCode) ProtoMessage() {} func (x *ResultCode) ProtoReflect() protoreflect.Message { - mi := &file_statedb_proto_msgTypes[11] + mi := &file_statedb_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -924,7 +1199,7 @@ func (x *ResultCode) ProtoReflect() protoreflect.Message { // Deprecated: Use ResultCode.ProtoReflect.Descriptor instead. func (*ResultCode) Descriptor() ([]byte, []int) { - return file_statedb_proto_rawDescGZIP(), []int{11} + return file_statedb_proto_rawDescGZIP(), []int{15} } func (x *ResultCode) GetCode() ResultCode_Code { @@ -942,7 +1217,7 @@ var file_statedb_proto_rawDesc = []byte{ 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x06, 0x76, 0x30, 0x5f, 0x30, 0x5f, 0x31, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x30, 0x30, 0x31, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x53, 0x65, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x30, 0x30, 0x31, 0x22, 0xd2, 0x01, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x07, 0x6f, 0x6c, 0x64, @@ -953,24 +1228,55 @@ var file_statedb_proto_rawDesc = []byte{ 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x6e, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x65, 0x61, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, - 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, - 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x6a, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xff, 0x03, 0x0a, 0x0b, + 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x25, 0x0a, 0x0f, 0x67, 0x65, 0x74, 0x5f, 0x64, + 0x62, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x67, 0x65, 0x74, 0x44, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x22, 0x95, + 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, + 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x04, 0x72, 0x6f, + 0x6f, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, + 0x25, 0x0a, 0x0f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x62, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6c, + 0x6f, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x67, 0x65, 0x74, 0x44, 0x62, 0x52, + 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x22, 0x6a, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, + 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xc2, 0x01, 0x0a, 0x0d, 0x4c, + 0x6f, 0x61, 0x64, 0x44, 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x08, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x62, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, + 0x44, 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x44, + 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x62, 0x12, + 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x1a, + 0x4e, 0x0a, 0x0c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xd9, 0x01, 0x0a, 0x14, 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, + 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x10, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x64, 0x62, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, 0x42, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, + 0x6d, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, 0x62, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x65, + 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x41, 0x0a, 0x13, 0x49, 0x6e, 0x70, 0x75, + 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc7, 0x05, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x07, @@ -994,40 +1300,65 @@ var file_statedb_proto_rawDesc = []byte{ 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, - 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x54, 0x0a, 0x0d, 0x53, 0x69, 0x62, 0x6c, 0x69, - 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x94, 0x03, - 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, - 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x04, 0x72, 0x6f, - 0x6f, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x08, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, - 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, - 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x28, 0x0a, 0x07, 0x69, 0x6e, 0x73, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x06, 0x69, 0x6e, 0x73, 0x4b, - 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6f, 0x6c, 0x64, 0x30, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x06, 0x69, 0x73, 0x4f, 0x6c, 0x64, 0x30, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, - 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x54, - 0x0a, 0x0d, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, - 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x0b, 0x64, 0x62, 0x5f, 0x72, 0x65, 0x61, 0x64, + 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x09, 0x64, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x2e, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x54, 0x0a, + 0x0d, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x62, + 0x6c, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x50, 0x0a, 0x0e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xdc, 0x04, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x65, 0x61, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x21, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, + 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x65, 0x61, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x41, 0x0a, + 0x08, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, + 0x12, 0x28, 0x0a, 0x07, 0x69, 0x6e, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x65, 0x61, 0x52, 0x06, 0x69, 0x6e, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, + 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, + 0x6e, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6f, 0x6c, + 0x64, 0x30, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4f, 0x6c, 0x64, 0x30, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x0b, 0x64, 0x62, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x5f, + 0x6c, 0x6f, 0x67, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x09, 0x64, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x2e, 0x0a, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x54, 0x0a, 0x0d, + 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x62, 0x6c, + 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x50, 0x0a, 0x0e, 0x44, 0x62, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6f, 0x67, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x44, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, @@ -1038,51 +1369,68 @@ var file_statedb_proto_rawDesc = []byte{ 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x22, 0x4d, 0x0a, 0x03, 0x46, 0x65, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x66, - 0x65, 0x30, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x30, 0x12, 0x10, 0x0a, - 0x03, 0x66, 0x65, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x31, 0x12, - 0x10, 0x0a, 0x03, 0x66, 0x65, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, - 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, - 0x66, 0x65, 0x33, 0x22, 0x27, 0x0a, 0x0b, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x04, 0x52, 0x07, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0xb1, 0x01, 0x0a, - 0x0a, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x63, - 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, - 0x65, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x72, 0x0a, 0x04, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4f, - 0x44, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, - 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, - 0x4e, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x42, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x44, 0x45, 0x5f, - 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, - 0x32, 0xdd, 0x02, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x42, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x38, 0x0a, - 0x03, 0x47, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3f, 0x0a, 0x0d, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x4d, 0x0a, 0x03, 0x46, 0x65, 0x61, 0x12, 0x10, 0x0a, 0x03, + 0x66, 0x65, 0x30, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x30, 0x12, 0x10, + 0x0a, 0x03, 0x66, 0x65, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x31, + 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, + 0x65, 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x03, 0x66, 0x65, 0x33, 0x22, 0x18, 0x0a, 0x06, 0x46, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x66, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x02, 0x66, 0x65, 0x22, 0x27, + 0x0a, 0x0b, 0x53, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x07, + 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0xd5, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x95, 0x01, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, + 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4f, 0x44, 0x45, + 0x5f, 0x44, 0x42, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, + 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x42, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x49, + 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, + 0x1e, 0x0a, 0x1a, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x4d, 0x54, 0x5f, 0x49, 0x4e, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x0e, 0x32, + 0xec, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x42, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x38, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x03, + 0x47, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x05, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x06, 0x4c, 0x6f, 0x61, 0x64, 0x44, 0x42, 0x12, 0x19, + 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, + 0x44, 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0d, 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x44, 0x42, 0x12, 0x20, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x44, 0x42, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, - 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, - 0x78, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, - 0x6b, 0x65, 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, - 0x74, 0x72, 0x65, 0x65, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x3c, 0x0a, 0x05, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x19, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x35, + 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, + 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, + 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x72, + 0x65, 0x65, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1098,63 +1446,83 @@ func file_statedb_proto_rawDescGZIP() []byte { } var file_statedb_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_statedb_proto_msgTypes = make([]protoimpl.MessageInfo, 14) +var file_statedb_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_statedb_proto_goTypes = []interface{}{ - (ResultCode_Code)(0), // 0: statedb.v1.ResultCode.Code - (*Version)(nil), // 1: statedb.v1.Version - (*SetRequest)(nil), // 2: statedb.v1.SetRequest - (*GetRequest)(nil), // 3: statedb.v1.GetRequest - (*SetProgramRequest)(nil), // 4: statedb.v1.SetProgramRequest - (*GetProgramRequest)(nil), // 5: statedb.v1.GetProgramRequest - (*SetResponse)(nil), // 6: statedb.v1.SetResponse - (*GetResponse)(nil), // 7: statedb.v1.GetResponse - (*SetProgramResponse)(nil), // 8: statedb.v1.SetProgramResponse - (*GetProgramResponse)(nil), // 9: statedb.v1.GetProgramResponse - (*Fea)(nil), // 10: statedb.v1.Fea - (*SiblingList)(nil), // 11: statedb.v1.SiblingList - (*ResultCode)(nil), // 12: statedb.v1.ResultCode - nil, // 13: statedb.v1.SetResponse.SiblingsEntry - nil, // 14: statedb.v1.GetResponse.SiblingsEntry - (*emptypb.Empty)(nil), // 15: google.protobuf.Empty + (ResultCode_Code)(0), // 0: statedb.v1.ResultCode.Code + (*Version)(nil), // 1: statedb.v1.Version + (*SetRequest)(nil), // 2: statedb.v1.SetRequest + (*GetRequest)(nil), // 3: statedb.v1.GetRequest + (*SetProgramRequest)(nil), // 4: statedb.v1.SetProgramRequest + (*GetProgramRequest)(nil), // 5: statedb.v1.GetProgramRequest + (*LoadDBRequest)(nil), // 6: statedb.v1.LoadDBRequest + (*LoadProgramDBRequest)(nil), // 7: statedb.v1.LoadProgramDBRequest + (*SetResponse)(nil), // 8: statedb.v1.SetResponse + (*GetResponse)(nil), // 9: statedb.v1.GetResponse + (*SetProgramResponse)(nil), // 10: statedb.v1.SetProgramResponse + (*GetProgramResponse)(nil), // 11: statedb.v1.GetProgramResponse + (*FlushResponse)(nil), // 12: statedb.v1.FlushResponse + (*Fea)(nil), // 13: statedb.v1.Fea + (*FeList)(nil), // 14: statedb.v1.FeList + (*SiblingList)(nil), // 15: statedb.v1.SiblingList + (*ResultCode)(nil), // 16: statedb.v1.ResultCode + nil, // 17: statedb.v1.LoadDBRequest.InputDbEntry + nil, // 18: statedb.v1.LoadProgramDBRequest.InputProgramDbEntry + nil, // 19: statedb.v1.SetResponse.SiblingsEntry + nil, // 20: statedb.v1.SetResponse.DbReadLogEntry + nil, // 21: statedb.v1.GetResponse.SiblingsEntry + nil, // 22: statedb.v1.GetResponse.DbReadLogEntry + (*emptypb.Empty)(nil), // 23: google.protobuf.Empty } var file_statedb_proto_depIdxs = []int32{ - 10, // 0: statedb.v1.SetRequest.old_root:type_name -> statedb.v1.Fea - 10, // 1: statedb.v1.SetRequest.key:type_name -> statedb.v1.Fea - 10, // 2: statedb.v1.GetRequest.root:type_name -> statedb.v1.Fea - 10, // 3: statedb.v1.GetRequest.key:type_name -> statedb.v1.Fea - 10, // 4: statedb.v1.SetProgramRequest.key:type_name -> statedb.v1.Fea - 10, // 5: statedb.v1.GetProgramRequest.key:type_name -> statedb.v1.Fea - 10, // 6: statedb.v1.SetResponse.old_root:type_name -> statedb.v1.Fea - 10, // 7: statedb.v1.SetResponse.new_root:type_name -> statedb.v1.Fea - 10, // 8: statedb.v1.SetResponse.key:type_name -> statedb.v1.Fea - 13, // 9: statedb.v1.SetResponse.siblings:type_name -> statedb.v1.SetResponse.SiblingsEntry - 10, // 10: statedb.v1.SetResponse.ins_key:type_name -> statedb.v1.Fea - 12, // 11: statedb.v1.SetResponse.result:type_name -> statedb.v1.ResultCode - 10, // 12: statedb.v1.GetResponse.root:type_name -> statedb.v1.Fea - 10, // 13: statedb.v1.GetResponse.key:type_name -> statedb.v1.Fea - 14, // 14: statedb.v1.GetResponse.siblings:type_name -> statedb.v1.GetResponse.SiblingsEntry - 10, // 15: statedb.v1.GetResponse.ins_key:type_name -> statedb.v1.Fea - 12, // 16: statedb.v1.GetResponse.result:type_name -> statedb.v1.ResultCode - 12, // 17: statedb.v1.SetProgramResponse.result:type_name -> statedb.v1.ResultCode - 12, // 18: statedb.v1.GetProgramResponse.result:type_name -> statedb.v1.ResultCode - 0, // 19: statedb.v1.ResultCode.code:type_name -> statedb.v1.ResultCode.Code - 11, // 20: statedb.v1.SetResponse.SiblingsEntry.value:type_name -> statedb.v1.SiblingList - 11, // 21: statedb.v1.GetResponse.SiblingsEntry.value:type_name -> statedb.v1.SiblingList - 2, // 22: statedb.v1.StateDBService.Set:input_type -> statedb.v1.SetRequest - 3, // 23: statedb.v1.StateDBService.Get:input_type -> statedb.v1.GetRequest - 4, // 24: statedb.v1.StateDBService.SetProgram:input_type -> statedb.v1.SetProgramRequest - 5, // 25: statedb.v1.StateDBService.GetProgram:input_type -> statedb.v1.GetProgramRequest - 15, // 26: statedb.v1.StateDBService.Flush:input_type -> google.protobuf.Empty - 6, // 27: statedb.v1.StateDBService.Set:output_type -> statedb.v1.SetResponse - 7, // 28: statedb.v1.StateDBService.Get:output_type -> statedb.v1.GetResponse - 8, // 29: statedb.v1.StateDBService.SetProgram:output_type -> statedb.v1.SetProgramResponse - 9, // 30: statedb.v1.StateDBService.GetProgram:output_type -> statedb.v1.GetProgramResponse - 15, // 31: statedb.v1.StateDBService.Flush:output_type -> google.protobuf.Empty - 27, // [27:32] is the sub-list for method output_type - 22, // [22:27] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 13, // 0: statedb.v1.SetRequest.old_root:type_name -> statedb.v1.Fea + 13, // 1: statedb.v1.SetRequest.key:type_name -> statedb.v1.Fea + 13, // 2: statedb.v1.GetRequest.root:type_name -> statedb.v1.Fea + 13, // 3: statedb.v1.GetRequest.key:type_name -> statedb.v1.Fea + 13, // 4: statedb.v1.SetProgramRequest.key:type_name -> statedb.v1.Fea + 13, // 5: statedb.v1.GetProgramRequest.key:type_name -> statedb.v1.Fea + 17, // 6: statedb.v1.LoadDBRequest.input_db:type_name -> statedb.v1.LoadDBRequest.InputDbEntry + 18, // 7: statedb.v1.LoadProgramDBRequest.input_program_db:type_name -> statedb.v1.LoadProgramDBRequest.InputProgramDbEntry + 13, // 8: statedb.v1.SetResponse.old_root:type_name -> statedb.v1.Fea + 13, // 9: statedb.v1.SetResponse.new_root:type_name -> statedb.v1.Fea + 13, // 10: statedb.v1.SetResponse.key:type_name -> statedb.v1.Fea + 19, // 11: statedb.v1.SetResponse.siblings:type_name -> statedb.v1.SetResponse.SiblingsEntry + 13, // 12: statedb.v1.SetResponse.ins_key:type_name -> statedb.v1.Fea + 20, // 13: statedb.v1.SetResponse.db_read_log:type_name -> statedb.v1.SetResponse.DbReadLogEntry + 16, // 14: statedb.v1.SetResponse.result:type_name -> statedb.v1.ResultCode + 13, // 15: statedb.v1.GetResponse.root:type_name -> statedb.v1.Fea + 13, // 16: statedb.v1.GetResponse.key:type_name -> statedb.v1.Fea + 21, // 17: statedb.v1.GetResponse.siblings:type_name -> statedb.v1.GetResponse.SiblingsEntry + 13, // 18: statedb.v1.GetResponse.ins_key:type_name -> statedb.v1.Fea + 22, // 19: statedb.v1.GetResponse.db_read_log:type_name -> statedb.v1.GetResponse.DbReadLogEntry + 16, // 20: statedb.v1.GetResponse.result:type_name -> statedb.v1.ResultCode + 16, // 21: statedb.v1.SetProgramResponse.result:type_name -> statedb.v1.ResultCode + 16, // 22: statedb.v1.GetProgramResponse.result:type_name -> statedb.v1.ResultCode + 16, // 23: statedb.v1.FlushResponse.result:type_name -> statedb.v1.ResultCode + 0, // 24: statedb.v1.ResultCode.code:type_name -> statedb.v1.ResultCode.Code + 14, // 25: statedb.v1.LoadDBRequest.InputDbEntry.value:type_name -> statedb.v1.FeList + 15, // 26: statedb.v1.SetResponse.SiblingsEntry.value:type_name -> statedb.v1.SiblingList + 14, // 27: statedb.v1.SetResponse.DbReadLogEntry.value:type_name -> statedb.v1.FeList + 15, // 28: statedb.v1.GetResponse.SiblingsEntry.value:type_name -> statedb.v1.SiblingList + 14, // 29: statedb.v1.GetResponse.DbReadLogEntry.value:type_name -> statedb.v1.FeList + 2, // 30: statedb.v1.StateDBService.Set:input_type -> statedb.v1.SetRequest + 3, // 31: statedb.v1.StateDBService.Get:input_type -> statedb.v1.GetRequest + 4, // 32: statedb.v1.StateDBService.SetProgram:input_type -> statedb.v1.SetProgramRequest + 5, // 33: statedb.v1.StateDBService.GetProgram:input_type -> statedb.v1.GetProgramRequest + 6, // 34: statedb.v1.StateDBService.LoadDB:input_type -> statedb.v1.LoadDBRequest + 7, // 35: statedb.v1.StateDBService.LoadProgramDB:input_type -> statedb.v1.LoadProgramDBRequest + 23, // 36: statedb.v1.StateDBService.Flush:input_type -> google.protobuf.Empty + 8, // 37: statedb.v1.StateDBService.Set:output_type -> statedb.v1.SetResponse + 9, // 38: statedb.v1.StateDBService.Get:output_type -> statedb.v1.GetResponse + 10, // 39: statedb.v1.StateDBService.SetProgram:output_type -> statedb.v1.SetProgramResponse + 11, // 40: statedb.v1.StateDBService.GetProgram:output_type -> statedb.v1.GetProgramResponse + 23, // 41: statedb.v1.StateDBService.LoadDB:output_type -> google.protobuf.Empty + 23, // 42: statedb.v1.StateDBService.LoadProgramDB:output_type -> google.protobuf.Empty + 12, // 43: statedb.v1.StateDBService.Flush:output_type -> statedb.v1.FlushResponse + 37, // [37:44] is the sub-list for method output_type + 30, // [30:37] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_statedb_proto_init() } @@ -1224,7 +1592,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetResponse); i { + switch v := v.(*LoadDBRequest); i { case 0: return &v.state case 1: @@ -1236,7 +1604,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetResponse); i { + switch v := v.(*LoadProgramDBRequest); i { case 0: return &v.state case 1: @@ -1248,7 +1616,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetProgramResponse); i { + switch v := v.(*SetResponse); i { case 0: return &v.state case 1: @@ -1260,7 +1628,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProgramResponse); i { + switch v := v.(*GetResponse); i { case 0: return &v.state case 1: @@ -1272,7 +1640,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Fea); i { + switch v := v.(*SetProgramResponse); i { case 0: return &v.state case 1: @@ -1284,7 +1652,7 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SiblingList); i { + switch v := v.(*GetProgramResponse); i { case 0: return &v.state case 1: @@ -1296,6 +1664,54 @@ func file_statedb_proto_init() { } } file_statedb_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlushResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_statedb_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Fea); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_statedb_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FeList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_statedb_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SiblingList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_statedb_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ResultCode); i { case 0: return &v.state @@ -1314,7 +1730,7 @@ func file_statedb_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_statedb_proto_rawDesc, NumEnums: 1, - NumMessages: 14, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/merkletree/pb/statedb_grpc.pb.go b/merkletree/pb/statedb_grpc.pb.go index 930344f01f..df6fc0a710 100644 --- a/merkletree/pb/statedb_grpc.pb.go +++ b/merkletree/pb/statedb_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.6 +// - protoc v3.21.12 // source: statedb.proto package pb @@ -27,7 +27,9 @@ type StateDBServiceClient interface { Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) SetProgram(ctx context.Context, in *SetProgramRequest, opts ...grpc.CallOption) (*SetProgramResponse, error) GetProgram(ctx context.Context, in *GetProgramRequest, opts ...grpc.CallOption) (*GetProgramResponse, error) - Flush(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + LoadDB(ctx context.Context, in *LoadDBRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + LoadProgramDB(ctx context.Context, in *LoadProgramDBRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + Flush(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*FlushResponse, error) } type stateDBServiceClient struct { @@ -74,8 +76,26 @@ func (c *stateDBServiceClient) GetProgram(ctx context.Context, in *GetProgramReq return out, nil } -func (c *stateDBServiceClient) Flush(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { +func (c *stateDBServiceClient) LoadDB(ctx context.Context, in *LoadDBRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/statedb.v1.StateDBService/LoadDB", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *stateDBServiceClient) LoadProgramDB(ctx context.Context, in *LoadProgramDBRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/statedb.v1.StateDBService/LoadProgramDB", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *stateDBServiceClient) Flush(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*FlushResponse, error) { + out := new(FlushResponse) err := c.cc.Invoke(ctx, "/statedb.v1.StateDBService/Flush", in, out, opts...) if err != nil { return nil, err @@ -91,7 +111,9 @@ type StateDBServiceServer interface { Get(context.Context, *GetRequest) (*GetResponse, error) SetProgram(context.Context, *SetProgramRequest) (*SetProgramResponse, error) GetProgram(context.Context, *GetProgramRequest) (*GetProgramResponse, error) - Flush(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + LoadDB(context.Context, *LoadDBRequest) (*emptypb.Empty, error) + LoadProgramDB(context.Context, *LoadProgramDBRequest) (*emptypb.Empty, error) + Flush(context.Context, *emptypb.Empty) (*FlushResponse, error) mustEmbedUnimplementedStateDBServiceServer() } @@ -111,7 +133,13 @@ func (UnimplementedStateDBServiceServer) SetProgram(context.Context, *SetProgram func (UnimplementedStateDBServiceServer) GetProgram(context.Context, *GetProgramRequest) (*GetProgramResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetProgram not implemented") } -func (UnimplementedStateDBServiceServer) Flush(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { +func (UnimplementedStateDBServiceServer) LoadDB(context.Context, *LoadDBRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadDB not implemented") +} +func (UnimplementedStateDBServiceServer) LoadProgramDB(context.Context, *LoadProgramDBRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method LoadProgramDB not implemented") +} +func (UnimplementedStateDBServiceServer) Flush(context.Context, *emptypb.Empty) (*FlushResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Flush not implemented") } func (UnimplementedStateDBServiceServer) mustEmbedUnimplementedStateDBServiceServer() {} @@ -199,6 +227,42 @@ func _StateDBService_GetProgram_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _StateDBService_LoadDB_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoadDBRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StateDBServiceServer).LoadDB(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/statedb.v1.StateDBService/LoadDB", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StateDBServiceServer).LoadDB(ctx, req.(*LoadDBRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _StateDBService_LoadProgramDB_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LoadProgramDBRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(StateDBServiceServer).LoadProgramDB(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/statedb.v1.StateDBService/LoadProgramDB", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(StateDBServiceServer).LoadProgramDB(ctx, req.(*LoadProgramDBRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _StateDBService_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -240,6 +304,14 @@ var StateDBService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetProgram", Handler: _StateDBService_GetProgram_Handler, }, + { + MethodName: "LoadDB", + Handler: _StateDBService_LoadDB_Handler, + }, + { + MethodName: "LoadProgramDB", + Handler: _StateDBService_LoadProgramDB_Handler, + }, { MethodName: "Flush", Handler: _StateDBService_Flush_Handler, diff --git a/merkletree/tree.go b/merkletree/tree.go index a885692f31..32f81565e6 100644 --- a/merkletree/tree.go +++ b/merkletree/tree.go @@ -9,6 +9,7 @@ import ( "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" "github.com/ethereum/go-ethereum/common" + "google.golang.org/protobuf/types/known/emptypb" ) // StateTree provides methods to access and modify state in merkletree @@ -312,3 +313,9 @@ func (tree *StateTree) setProgram(ctx context.Context, key []uint64, data []byte }) return err } + +// Flush flushes all changes to the persistent storage. +func (tree *StateTree) Flush(ctx context.Context) error { + _, err := tree.grpcClient.Flush(ctx, &emptypb.Empty{}) + return err +} diff --git a/metrics/api.go b/metrics/api.go new file mode 100644 index 0000000000..c21e2cca50 --- /dev/null +++ b/metrics/api.go @@ -0,0 +1,16 @@ +package metrics + +const ( + //Endpoint the endpoint for exposing the metrics + Endpoint = "/metrics" + // ProfilingIndexEndpoint the endpoint for exposing the profiling metrics + ProfilingIndexEndpoint = "/debug/pprof/" + // ProfileEndpoint the endpoint for exposing the profile of the profiling metrics + ProfileEndpoint = "/debug/pprof/profile" + // ProfilingCmdEndpoint the endpoint for exposing the command-line of profiling metrics + ProfilingCmdEndpoint = "/debug/pprof/cmdline" + // ProfilingSymbolEndpoint the endpoint for exposing the symbol of profiling metrics + ProfilingSymbolEndpoint = "/debug/pprof/symbol" + // ProfilingTraceEndpoint the endpoint for exposing the trace of profiling metrics + ProfilingTraceEndpoint = "/debug/pprof/trace" +) diff --git a/metrics/config.go b/metrics/config.go new file mode 100644 index 0000000000..742e54aae5 --- /dev/null +++ b/metrics/config.go @@ -0,0 +1,11 @@ +package metrics + +// Config represents the configuration of the metrics +type Config struct { + Host string `mapstructure:"Host"` + Port int `mapstructure:"Port"` + Enabled bool `mapstructure:"Enabled"` + ProfilingHost string `mapstructure:"ProfilingHost"` + ProfilingPort int `mapstructure:"ProfilingPort"` + ProfilingEnabled bool `mapstructure:"ProfilingEnabled"` +} diff --git a/metrics/prometheus.go b/metrics/prometheus.go new file mode 100644 index 0000000000..4e091b8da0 --- /dev/null +++ b/metrics/prometheus.go @@ -0,0 +1,677 @@ +package metrics + +import ( + "net/http" + "sync" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +var ( + storageMutex sync.RWMutex + registerer prometheus.Registerer + gauges map[string]prometheus.Gauge + counters map[string]prometheus.Counter + counterVecs map[string]*prometheus.CounterVec + histograms map[string]prometheus.Histogram + histogramVecs map[string]*prometheus.HistogramVec + summaries map[string]prometheus.Summary + initialized bool + initOnce sync.Once +) + +// CounterVecOpts holds options for the CounterVec type. +type CounterVecOpts struct { + prometheus.CounterOpts + Labels []string +} + +// HistogramVecOpts holds options for the HistogramVec type. +type HistogramVecOpts struct { + prometheus.HistogramOpts + Labels []string +} + +// Init initializes the package variables. +func Init() { + initOnce.Do(func() { + storageMutex = sync.RWMutex{} + registerer = prometheus.DefaultRegisterer + gauges = make(map[string]prometheus.Gauge) + counters = make(map[string]prometheus.Counter) + counterVecs = make(map[string]*prometheus.CounterVec) + histograms = make(map[string]prometheus.Histogram) + histogramVecs = make(map[string]*prometheus.HistogramVec) + summaries = make(map[string]prometheus.Summary) + initialized = true + }) +} + +// Handler returns the Prometheus http handler. +func Handler() http.Handler { + return promhttp.Handler() +} + +// RegisterGauges registers the provided gauge metrics to the Prometheus +// registerer. +func RegisterGauges(opts ...prometheus.GaugeOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerGaugeIfNotExists(options) + } +} + +// UnregisterGauges unregisters the provided gauge metrics from the Prometheus +// registerer. +func UnregisterGauges(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterGaugeIfExists(name) + } +} + +// Gauge retrieves gauge metric by name +func Gauge(name string) (gauge prometheus.Gauge, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + if gauge, exist = gauges[name]; !exist { + return nil, exist + } + + return gauge, exist +} + +// GaugeSet sets the value for gauge with the given name. +func GaugeSet(name string, value float64) { + if !initialized { + return + } + + if c, ok := Gauge(name); ok { + c.Set(value) + } +} + +// GaugeInc increments the gauge with the given name. +func GaugeInc(name string) { + if !initialized { + return + } + + if g, ok := Gauge(name); ok { + g.Inc() + } +} + +// GaugeDec decrements the gauge with the given name. +func GaugeDec(name string) { + if !initialized { + return + } + + if g, ok := Gauge(name); ok { + g.Dec() + } +} + +// RegisterCounters registers the provided counter metrics to the Prometheus +// registerer. +func RegisterCounters(opts ...prometheus.CounterOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerCounterIfNotExists(options) + } +} + +// Counter retrieves counter metric by name +func Counter(name string) (counter prometheus.Counter, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + if counter, exist = counters[name]; !exist { + return nil, exist + } + + return counter, exist +} + +// CounterInc increments the counter with the given name. +func CounterInc(name string) { + if !initialized { + return + } + + if c, ok := Counter(name); ok { + c.Inc() + } +} + +// CounterAdd increments the counter with the given name. +func CounterAdd(name string, value float64) { + if !initialized { + return + } + + if c, ok := Counter(name); ok { + c.Add(value) + } +} + +// UnregisterCounters unregisters the provided counter metrics from the +// Prometheus registerer. +func UnregisterCounters(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterCounterIfExists(name) + } +} + +// RegisterCounterVecs registers the provided counter vec metrics to the +// Prometheus registerer. +func RegisterCounterVecs(opts ...CounterVecOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerCounterVecIfNotExists(options) + } +} + +// CounterVec retrieves counter ver metric by name +func CounterVec(name string) (counterVec *prometheus.CounterVec, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + counterVec, exist = counterVecs[name] + + return counterVec, exist +} + +// CounterVecInc increments the counter vec with the given name and label. +func CounterVecInc(name string, label string) { + if !initialized { + return + } + + if cv, ok := CounterVec(name); ok { + cv.WithLabelValues(label).Inc() + } +} + +// CounterVecAdd increments the counter vec by the given value, with the given +// name and label. +func CounterVecAdd(name string, label string, value float64) { + if !initialized { + return + } + + if cv, ok := CounterVec(name); ok { + cv.WithLabelValues(label).Add(value) + } +} + +// UnregisterCounterVecs unregisters the provided counter vec metrics from the +// Prometheus registerer. +func UnregisterCounterVecs(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterCounterVecIfExists(name) + } +} + +// RegisterHistograms registers the provided histogram metrics to the +// Prometheus registerer. +func RegisterHistograms(opts ...prometheus.HistogramOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerHistogramIfNotExists(options) + } +} + +// Histogram retrieves histogram metric by name +func Histogram(name string) (histogram prometheus.Histogram, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + if histogram, exist = histograms[name]; !exist { + return nil, exist + } + + return histogram, exist +} + +// HistogramObserve observes the histogram from the given start time. +func HistogramObserve(name string, value float64) { + if !initialized { + return + } + + if histo, ok := Histogram(name); ok { + histo.Observe(value) + } +} + +// UnregisterHistogram unregisters the provided histogram metrics from the +// Prometheus registerer. +func UnregisterHistogram(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterHistogramIfExists(name) + } +} + +// RegisterHistogramVecs registers the provided histogram vec metrics to the +// Prometheus registerer. +func RegisterHistogramVecs(opts ...HistogramVecOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerHistogramVecIfNotExists(options) + } +} + +// HistogramVec retrieves histogram ver metric by name +func HistogramVec(name string) (histgramVec *prometheus.HistogramVec, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + histgramVec, exist = histogramVecs[name] + + return histgramVec, exist +} + +// HistogramVecObserve observes the histogram vec with the given name, label and value. +func HistogramVecObserve(name string, label string, value float64) { + if !initialized { + return + } + + if cv, ok := HistogramVec(name); ok { + cv.WithLabelValues(label).Observe(value) + } +} + +// UnregisterHistogramVecs unregisters the provided histogram vec metrics from the +// Prometheus registerer. +func UnregisterHistogramVecs(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterHistogramVecIfExists(name) + } +} + +// RegisterSummaries registers the provided summary metrics to the Prometheus +// registerer. +func RegisterSummaries(opts ...prometheus.SummaryOpts) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, options := range opts { + registerSummaryIfNotExists(options) + } +} + +// Summary retrieves summary metric by name +func Summary(name string) (summary prometheus.Summary, exist bool) { + if !initialized { + return + } + + storageMutex.RLock() + defer storageMutex.RUnlock() + + if summary, exist = summaries[name]; !exist { + return nil, exist + } + + return summary, exist +} + +// UnregisterSummaries unregisters the provided summary metrics from the +// Prometheus registerer. +func UnregisterSummaries(names ...string) { + if !initialized { + return + } + + storageMutex.Lock() + defer storageMutex.Unlock() + + for _, name := range names { + unregisterSummaryIfExists(name) + } +} + +// registerGaugeIfNotExists registers single gauge metric if not exists +func registerGaugeIfNotExists(opts prometheus.GaugeOpts) { + log := log.WithFields("metricName", opts.Name) + if _, exist := gauges[opts.Name]; exist { + log.Warn("Gauge metric already exists.") + return + } + + log.Debug("Creating Gauge Metric...") + gauge := prometheus.NewGauge(opts) + log.Debugf("Gauge Metric successfully created! Labels: %p", opts.ConstLabels) + + log.Debug("Registering Gauge Metric...") + registerer.MustRegister(gauge) + log.Debug("Gauge Metric successfully registered!") + + gauges[opts.Name] = gauge +} + +// unregisterGaugeIfExists unregisters single gauge metric if exists +func unregisterGaugeIfExists(name string) { + var ( + gauge prometheus.Gauge + ok bool + ) + + log := log.WithFields("metricName", name) + if gauge, ok = gauges[name]; !ok { + log.Warn("Trying to delete non-existing Gauge metrics.") + return + } + + log.Debug("Unregistering Gauge Metric...") + ok = registerer.Unregister(gauge) + if !ok { + log.Error("Failed to unregister Gauge Metric.") + return + } + delete(gauges, name) + log.Debug("Gauge Metric successfully unregistered!") +} + +// registerCounterIfNotExists registers single counter metric if not exists +func registerCounterIfNotExists(opts prometheus.CounterOpts) { + log := log.WithFields("metricName", opts.Name) + if _, exist := counters[opts.Name]; exist { + log.Warn("Counter metric already exists.") + return + } + + log.Debug("Creating Counter Metric...") + counter := prometheus.NewCounter(opts) + log.Debugf("Counter Metric successfully created! Labels: %p", opts.ConstLabels) + + log.Debug("Registering Counter Metric...") + registerer.MustRegister(counter) + log.Debug("Counter Metric successfully registered!") + + counters[opts.Name] = counter +} + +// unregisterCounterIfExists unregisters single counter metric if exists +func unregisterCounterIfExists(name string) { + var ( + counter prometheus.Counter + ok bool + ) + + log := log.WithFields("metricName", name) + if counter, ok = counters[name]; !ok { + log.Warn("Trying to delete non-existing Counter counter.") + return + } + + log.Debug("Unregistering Counter Metric...") + ok = registerer.Unregister(counter) + if !ok { + log.Error("Failed to unregister Counter Metric.") + return + } + delete(counters, name) + log.Debugf("Counter Metric '%v' successfully unregistered!", name) +} + +// registerCounterVecIfNotExists registers single counter vec metric if not exists +func registerCounterVecIfNotExists(opts CounterVecOpts) { + log := log.WithFields("metricName", opts.Name) + if _, exist := counterVecs[opts.Name]; exist { + log.Warn("Counter vec metric already exists.") + return + } + + log.Debug("Creating Counter Vec Metric...") + counterVec := prometheus.NewCounterVec(opts.CounterOpts, opts.Labels) + log.Debugf("Counter Vec Metric successfully created! Labels: %p", opts.ConstLabels) + + log.Debug("Registering Counter Vec Metric...") + registerer.MustRegister(counterVec) + log.Debug("Counter Vec Metric successfully registered!") + + counterVecs[opts.Name] = counterVec +} + +// unregisterCounterVecIfExists unregisters single counter metric if exists +func unregisterCounterVecIfExists(name string) { + var ( + counterVec *prometheus.CounterVec + ok bool + ) + + log := log.WithFields("metricName", name) + if counterVec, ok = counterVecs[name]; !ok { + log.Warn("Trying to delete non-existing Counter Vec counter.") + return + } + + log.Debug("Unregistering Counter Vec Metric...") + ok = registerer.Unregister(counterVec) + if !ok { + log.Error("Failed to unregister Counter Vec Metric.") + return + } + delete(counterVecs, name) + log.Debug("Counter Vec Metric successfully unregistered!") +} + +// registerHistogramIfNotExists registers single histogram metric if not exists +func registerHistogramIfNotExists(opts prometheus.HistogramOpts) { + log := log.WithFields("metricName", opts.Name) + if _, exist := histograms[opts.Name]; exist { + log.Warn("Histogram metric already exists.") + return + } + + log.Debug("Creating Histogram Metric...") + histogram := prometheus.NewHistogram(opts) + log.Debugf("Histogram Metric successfully created! Labels: %p", opts.ConstLabels) + + log.Debug("Registering Histogram Metric...") + registerer.MustRegister(histogram) + log.Debug("Histogram Metric successfully registered!") + + histograms[opts.Name] = histogram +} + +// unregisterHistogramIfExists unregisters single histogram metric if exists +func unregisterHistogramIfExists(name string) { + var ( + histogram prometheus.Histogram + ok bool + ) + + log := log.WithFields("metricName", name) + if histogram, ok = histograms[name]; !ok { + log.Warn("Trying to delete non-existing Histogram histogram.") + return + } + + log.Debug("Unregistering Histogram Metric...") + ok = registerer.Unregister(histogram) + if !ok { + log.Error("Failed to unregister Histogram Metric.") + return + } + delete(histograms, name) + log.Debug("Histogram Metric successfully unregistered!") +} + +// registerHistogramVecIfNotExists unregisters single counter metric if exists +func registerHistogramVecIfNotExists(opts HistogramVecOpts) { + if _, exist := histogramVecs[opts.Name]; exist { + log.Warnf("Histogram vec metric '%v' already exists.", opts.Name) + return + } + + log.Infof("Creating Histogram Vec Metric '%v' ...", opts.Name) + histogramVec := prometheus.NewHistogramVec(opts.HistogramOpts, opts.Labels) + log.Infof("Histogram Vec Metric '%v' successfully created! Labels: %p", opts.Name, opts.ConstLabels) + + log.Infof("Registering Histogram Vec Metric '%v' ...", opts.Name) + registerer.MustRegister(histogramVec) + log.Infof("Histogram Vec Metric '%v' successfully registered!", opts.Name) + + histogramVecs[opts.Name] = histogramVec +} + +// unregisterHistogramVecIfExists unregisters single histogram metric if exists +func unregisterHistogramVecIfExists(name string) { + var ( + histogramVec *prometheus.HistogramVec + ok bool + ) + + if histogramVec, ok = histogramVecs[name]; !ok { + log.Warnf("Trying to delete non-existing Histogram Vec '%v'.", name) + return + } + + log.Infof("Unregistering Histogram Vec Metric '%v' ...", name) + ok = registerer.Unregister(histogramVec) + if !ok { + log.Errorf("Failed to unregister Histogram Vec Metric '%v'.", name) + return + } + delete(histogramVecs, name) + log.Infof("Histogram Vec Metric '%v' successfully unregistered!", name) +} + +// registerSummaryIfNotExists registers single summary metric if not exists +func registerSummaryIfNotExists(opts prometheus.SummaryOpts) { + log := log.WithFields("metricName", opts.Name) + if _, exist := summaries[opts.Name]; exist { + log.Warn("Summary metric already exists.") + return + } + + log.Debug("Creating Summary Metric...") + summary := prometheus.NewSummary(opts) + log.Debugf("Summary Metric successfully created! Labels: %p", opts.ConstLabels) + + log.Debug("Registering Summary Metric...") + registerer.MustRegister(summary) + log.Debug("Summary Metric successfully registered!") + + summaries[opts.Name] = summary +} + +// unregisterSummaryIfExists unregisters single summary metric if exists +func unregisterSummaryIfExists(name string) { + var ( + summary prometheus.Summary + ok bool + ) + + log := log.WithFields("metricName", name) + if summary, ok = summaries[name]; !ok { + log.Warn("Trying to delete non-existing Summary summary.") + return + } + + log.Debug("Unregistering Summary Metric...") + ok = registerer.Unregister(summary) + if !ok { + log.Error("Failed to unregister Summary Metric.") + return + } + delete(summaries, name) + log.Debug("Summary Metric successfully unregistered!") +} diff --git a/metrics/prometheus_test.go b/metrics/prometheus_test.go new file mode 100644 index 0000000000..3cf5683e15 --- /dev/null +++ b/metrics/prometheus_test.go @@ -0,0 +1,371 @@ +package metrics + +import ( + "sync" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + dto "github.com/prometheus/client_model/go" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + gaugeName = "gaugeName" + gaugeOpts = prometheus.GaugeOpts{Name: gaugeName} + gauge prometheus.Gauge + counterName = "counterName" + counterOpts = prometheus.CounterOpts{Name: counterName} + counter prometheus.Counter + counterVecName = "counterVecName" + counterVecLabelName = "counterVecLabelName" + counterVecLabelVal = "counterVecLabelVal" + counterVecOpts = CounterVecOpts{prometheus.CounterOpts{Name: counterVecName}, []string{counterVecLabelName}} + counterVec *prometheus.CounterVec + histogramName = "histogramName" + histogramOpts = prometheus.HistogramOpts{Name: histogramName, Buckets: []float64{0.5, 10, 20}} + histogram prometheus.Histogram + histogramVecName = "histogramVecName" + histogramVecLabelName = "histogramVecLabelName" + histogramVecLabelVal = "histogramVecLabelVal" + histogramVecOpts = HistogramVecOpts{prometheus.HistogramOpts{Name: histogramVecName}, []string{histogramVecLabelName}} + histogramVec *prometheus.HistogramVec + summaryName = "summaryName" + summaryOpts = prometheus.SummaryOpts{Name: summaryName} + summary = prometheus.NewSummary(summaryOpts) +) + +func setup() { + Init() + gauge = prometheus.NewGauge(gaugeOpts) + counter = prometheus.NewCounter(counterOpts) + counterVec = prometheus.NewCounterVec(counterVecOpts.CounterOpts, counterVecOpts.Labels) + histogram = prometheus.NewHistogram(histogramOpts) + histogramVec = prometheus.NewHistogramVec(histogramVecOpts.HistogramOpts, histogramVecOpts.Labels) + summary = prometheus.NewSummary(summaryOpts) + + // Overriding registerer to be able to do the unit tests independently + registerer = prometheus.NewRegistry() +} + +func cleanup() { + initialized = false + initOnce = sync.Once{} +} + +func TestHandler(t *testing.T) { + setup() + defer cleanup() + + actual := Handler() + + assert.NotNil(t, actual) +} + +func TestRegisterGauges(t *testing.T) { + setup() + defer cleanup() + gaugesOpts := []prometheus.GaugeOpts{gaugeOpts} + + RegisterGauges(gaugesOpts...) + + assert.Len(t, gauges, 1) +} + +func TestGauge(t *testing.T) { + setup() + defer cleanup() + gauges[gaugeName] = gauge + + actual, exist := Gauge(gaugeName) + + assert.True(t, exist) + assert.Equal(t, gauge, actual) +} + +func TestGaugeSet(t *testing.T) { + setup() + defer cleanup() + gauges[gaugeName] = gauge + expected := float64(2) + + GaugeSet(gaugeName, expected) + actual := testutil.ToFloat64(gauge) + + assert.Equal(t, expected, actual) +} + +func TestGaugeInc(t *testing.T) { + setup() + defer cleanup() + gauges[gaugeName] = gauge + expected := float64(1) + + GaugeInc(gaugeName) + actual := testutil.ToFloat64(gauge) + + assert.Equal(t, expected, actual) +} + +func TestGaugeDec(t *testing.T) { + setup() + defer cleanup() + gauges[gaugeName] = gauge + gauge.Set(2) + expected := float64(1) + + GaugeDec(gaugeName) + actual := testutil.ToFloat64(gauge) + + assert.Equal(t, expected, actual) +} + +func TestUnregisterGauges(t *testing.T) { + setup() + defer cleanup() + RegisterGauges(gaugeOpts) + + UnregisterGauges(gaugeName) + + assert.Len(t, gauges, 0) +} + +func TestRegisterCounters(t *testing.T) { + setup() + defer cleanup() + countersOpts := []prometheus.CounterOpts{counterOpts} + + RegisterCounters(countersOpts...) + + assert.Len(t, counters, 1) +} + +func TestCounter(t *testing.T) { + setup() + defer cleanup() + counters[counterName] = counter + + actual, exist := Counter(counterName) + + assert.True(t, exist) + assert.Equal(t, counter, actual) +} + +func TestCounterInc(t *testing.T) { + setup() + defer cleanup() + counters[counterName] = counter + expected := float64(1) + + CounterInc(counterName) + actual := testutil.ToFloat64(counter) + + assert.Equal(t, expected, actual) +} + +func TestCounterAdd(t *testing.T) { + setup() + defer cleanup() + counters[counterName] = counter + expected := float64(2) + + CounterAdd(counterName, expected) + actual := testutil.ToFloat64(counter) + + assert.Equal(t, expected, actual) +} + +func TestUnregisterCounters(t *testing.T) { + setup() + defer cleanup() + RegisterCounters(counterOpts) + + UnregisterCounters(counterName) + + assert.Len(t, counters, 0) +} + +func TestRegisterCounterVecs(t *testing.T) { + setup() + defer cleanup() + counterVecsOpts := []CounterVecOpts{counterVecOpts} + + RegisterCounterVecs(counterVecsOpts...) + + assert.Len(t, counterVecs, 1) +} + +func TestCounterVec(t *testing.T) { + setup() + defer cleanup() + counterVecs[counterVecName] = counterVec + + actual, exist := CounterVec(counterVecName) + + assert.True(t, exist) + assert.Equal(t, counterVec, actual) +} + +func TestCounterVecInc(t *testing.T) { + setup() + defer cleanup() + counterVecs[counterVecName] = counterVec + expected := float64(1) + + CounterVecInc(counterVecName, counterVecLabelVal) + currCounterVec, err := counterVec.GetMetricWithLabelValues(counterVecLabelVal) + require.NoError(t, err) + actual := testutil.ToFloat64(currCounterVec) + + assert.Equal(t, expected, actual) +} + +func TestCounterVecAdd(t *testing.T) { + setup() + defer cleanup() + counterVecs[counterVecName] = counterVec + expected := float64(2) + + CounterVecAdd(counterVecName, counterVecLabelVal, expected) + currCounterVec, err := counterVec.GetMetricWithLabelValues(counterVecLabelVal) + require.NoError(t, err) + actual := testutil.ToFloat64(currCounterVec) + + assert.Equal(t, expected, actual) +} + +func TestUnregisterCounterVecs(t *testing.T) { + setup() + defer cleanup() + RegisterCounterVecs(counterVecOpts) + + UnregisterCounterVecs(counterVecName) + + assert.Len(t, counterVecs, 0) +} + +func TestRegisterHistograms(t *testing.T) { + setup() + defer cleanup() + histogramsOpts := []prometheus.HistogramOpts{histogramOpts} + + RegisterHistograms(histogramsOpts...) + + assert.Len(t, histograms, 1) +} + +func TestHistogram(t *testing.T) { + setup() + defer cleanup() + histograms[histogramName] = histogram + + actual, exist := Histogram(histogramName) + + assert.True(t, exist) + assert.Equal(t, histogram, actual) +} + +func TestHistogramObserve(t *testing.T) { + setup() + defer cleanup() + histograms[histogramName] = histogram + + expected := 42.0 + + HistogramObserve(histogramName, expected) + + m := &dto.Metric{} + require.NoError(t, histogram.Write(m)) + h := m.GetHistogram() + actual := h.GetSampleSum() + assert.Equal(t, expected, actual) +} + +func TestUnregisterHistograms(t *testing.T) { + setup() + defer cleanup() + RegisterHistograms(histogramOpts) + + UnregisterHistogram(histogramName) + + assert.Len(t, histograms, 0) +} + +func TestRegisterHistogramVecs(t *testing.T) { + setup() + defer cleanup() + histogramVecsOpts := []HistogramVecOpts{histogramVecOpts} + + RegisterHistogramVecs(histogramVecsOpts...) + + assert.Len(t, histogramVecs, 1) +} + +func TestHistogramVec(t *testing.T) { + setup() + defer cleanup() + histogramVecs[histogramVecName] = histogramVec + + actual, exist := HistogramVec(histogramVecName) + + assert.True(t, exist) + assert.Equal(t, histogramVec, actual) +} + +func TestHistogramVecObserve(t *testing.T) { + setup() + defer cleanup() + histogramVecs[histogramVecName] = histogramVec + expected := float64(2) + + HistogramVecObserve(histogramVecName, histogramVecLabelVal, expected) + + currHistogramVec := histogramVec.WithLabelValues(histogramVecLabelVal) + m := &dto.Metric{} + require.NoError(t, currHistogramVec.(prometheus.Histogram).Write(m)) + h := m.GetHistogram() + actual := h.GetSampleSum() + assert.Equal(t, expected, actual) +} + +func TestUnregisterHistogramVecs(t *testing.T) { + setup() + defer cleanup() + RegisterHistogramVecs(histogramVecOpts) + + UnregisterHistogramVecs(histogramVecName) + + assert.Len(t, histogramVecs, 0) +} + +func TestRegisterSummaries(t *testing.T) { + setup() + defer cleanup() + summariesOpts := []prometheus.SummaryOpts{summaryOpts} + + RegisterSummaries(summariesOpts...) + + assert.Len(t, summaries, 1) +} + +func TestSummary(t *testing.T) { + setup() + defer cleanup() + summaries[summaryName] = summary + + actual, exist := Summary(summaryName) + + assert.True(t, exist) + assert.Equal(t, summary, actual) +} + +func TestUnregisterSummaries(t *testing.T) { + setup() + defer cleanup() + RegisterSummaries(summaryOpts) + + UnregisterSummaries(summaryName) + + assert.Len(t, summaries, 0) +} diff --git a/pool/config.go b/pool/config.go new file mode 100644 index 0000000000..247f6114ba --- /dev/null +++ b/pool/config.go @@ -0,0 +1,31 @@ +package pool + +import ( + "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/db" +) + +// Config is the pool configuration +type Config struct { + // IntervalToRefreshBlockedAddresses is the time it takes to sync the + // blocked address list from db to memory + IntervalToRefreshBlockedAddresses types.Duration `mapstructure:"IntervalToRefreshBlockedAddresses"` + + // MaxTxBytesSize is the max size of a transaction in bytes + MaxTxBytesSize uint64 `mapstructure:"MaxTxBytesSize"` + + // MaxTxDataBytesSize is the max size of the data field of a transaction in bytes + MaxTxDataBytesSize int `mapstructure:"MaxTxDataBytesSize"` + + // DB is the database configuration + DB db.Config `mapstructure:"DB"` + + // DefaultMinGasPriceAllowed is the default min gas price to suggest + DefaultMinGasPriceAllowed uint64 `mapstructure:"DefaultMinGasPriceAllowed"` + + // MinAllowedGasPriceInterval is the interval to look back of the suggested min gas price for a tx + MinAllowedGasPriceInterval types.Duration `mapstructure:"MinAllowedGasPriceInterval"` + + // PollMinAllowedGasPriceInterval is the interval to poll the suggested min gas price for a tx + PollMinAllowedGasPriceInterval types.Duration `mapstructure:"PollMinAllowedGasPriceInterval"` +} diff --git a/pool/errors.go b/pool/errors.go index 285b8f2760..6f373ad206 100644 --- a/pool/errors.go +++ b/pool/errors.go @@ -27,6 +27,9 @@ var ( // ErrInvalidSender is returned if the transaction contains an invalid signature. ErrInvalidSender = errors.New("invalid sender") + // ErrBlockedSender is returned if the transaction is sent by a blocked account. + ErrBlockedSender = errors.New("blocked sender") + // ErrNonceTooLow is returned if the nonce of a transaction is lower than the // one present in the local chain. ErrNonceTooLow = errors.New("nonce too low") @@ -34,4 +37,14 @@ var ( // ErrInsufficientFunds is returned if the total cost of executing a transaction // is higher than the balance of the user's account. ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value") + + // ErrIntrinsicGas is returned if the transaction is specified to use less gas + // than required to start the invocation. + ErrIntrinsicGas = errors.New("intrinsic gas too low") + + // ErrGasUintOverflow is returned when calculating gas usage. + ErrGasUintOverflow = errors.New("gas uint64 overflow") + + // ErrGasPrice is returned if the transaction has specified lower gas price than the minimum allowed. + ErrGasPrice = errors.New("gas price too low") ) diff --git a/pool/interfaces.go b/pool/interfaces.go index ce268f2c81..c887a32754 100644 --- a/pool/interfaces.go +++ b/pool/interfaces.go @@ -5,6 +5,7 @@ import ( "math/big" "time" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" @@ -13,25 +14,32 @@ import ( type storage interface { AddTx(ctx context.Context, tx Transaction) error CountTransactionsByStatus(ctx context.Context, status TxStatus) (uint64, error) - DeleteTxsByHashes(ctx context.Context, hashes []common.Hash) error + DeleteTransactionsByHashes(ctx context.Context, hashes []common.Hash) error GetGasPrice(ctx context.Context) (uint64, error) GetNonce(ctx context.Context, address common.Address) (uint64, error) GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) GetTxsByFromAndNonce(ctx context.Context, from common.Address, nonce uint64) ([]Transaction, error) - GetTxsByStatus(ctx context.Context, state TxStatus, isClaims bool, limit uint64) ([]Transaction, error) + GetTxsByStatus(ctx context.Context, state TxStatus, limit uint64) ([]Transaction, error) + GetNonWIPTxsByStatus(ctx context.Context, status TxStatus, limit uint64) ([]Transaction, error) IsTxPending(ctx context.Context, hash common.Hash) (bool, error) SetGasPrice(ctx context.Context, gasPrice uint64) error - UpdateTxsStatus(ctx context.Context, hashes []string, newStatus TxStatus) error - UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus TxStatus) error - GetTxs(ctx context.Context, filterStatus TxStatus, isClaims bool, minGasPrice, limit uint64) ([]*Transaction, error) + UpdateTxsStatus(ctx context.Context, updateInfo []TxStatusUpdateInfo) error + UpdateTxStatus(ctx context.Context, updateInfo TxStatusUpdateInfo) error + UpdateTxWIPStatus(ctx context.Context, hash common.Hash, isWIP bool) error + GetTxs(ctx context.Context, filterStatus TxStatus, minGasPrice, limit uint64) ([]*Transaction, error) GetTxFromAddressFromByHash(ctx context.Context, hash common.Hash) (common.Address, uint64, error) GetTxByHash(ctx context.Context, hash common.Hash) (*Transaction, error) - IncrementFailedCounter(ctx context.Context, hashes []string) error + GetTxZkCountersByHash(ctx context.Context, hash common.Hash) (*state.ZKCounters, error) + DeleteTransactionByHash(ctx context.Context, hash common.Hash) error + MarkWIPTxsAsPending(ctx context.Context) error + GetAllAddressesBlocked(ctx context.Context) ([]common.Address, error) + MinGasPriceSince(ctx context.Context, timestamp time.Time) (uint64, error) } type stateInterface interface { - GetBalance(ctx context.Context, address common.Address, batchNumber uint64, dbTx pgx.Tx) (*big.Int, error) - GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) - GetNonce(ctx context.Context, address common.Address, batchNumber uint64, dbTx pgx.Tx) (uint64, error) + GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) + GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) + GetNonce(ctx context.Context, address common.Address, root common.Hash) (uint64, error) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) + PreProcessTransaction(ctx context.Context, tx *types.Transaction, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) } diff --git a/pool/pgpoolstorage/pgpoolstorage.go b/pool/pgpoolstorage/pgpoolstorage.go index 5ca888d70a..4ae9fd2513 100644 --- a/pool/pgpoolstorage/pgpoolstorage.go +++ b/pool/pgpoolstorage/pgpoolstorage.go @@ -16,11 +16,6 @@ import ( "github.com/jackc/pgx/v4/pgxpool" ) -var ( - // ErrNotFound indicates an object has not been found for the search criteria used - ErrNotFound = errors.New("object not found") -) - // PostgresPoolStorage is an implementation of the Pool interface // that uses a postgres database to store the data type PostgresPoolStorage struct { @@ -57,8 +52,9 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er gasPrice := tx.GasPrice().Uint64() nonce := tx.Nonce() + sql := ` - INSERT INTO pool.txs + INSERT INTO pool.transaction ( hash, encoded, @@ -66,7 +62,6 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er status, gas_price, nonce, - is_claims, cumulative_gas_used, used_keccak_hashes, used_poseidon_hashes, @@ -76,10 +71,30 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er used_binaries, used_steps, received_at, - from_address + from_address, + is_wip, + ip ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) + ON CONFLICT (hash) DO UPDATE SET + encoded = $2, + decoded = $3, + status = $4, + gas_price = $5, + nonce = $6, + cumulative_gas_used = $7, + used_keccak_hashes = $8, + used_poseidon_hashes = $9, + used_poseidon_paddings = $10, + used_mem_aligns = $11, + used_arithmetics = $12, + used_binaries = $13, + used_steps = $14, + received_at = $15, + from_address = $16, + is_wip = $17, + ip = $18 ` // Get FromAddress from the JSON data @@ -96,7 +111,6 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er tx.Status, gasPrice, nonce, - tx.IsClaims, tx.CumulativeGasUsed, tx.UsedKeccakHashes, tx.UsedPoseidonHashes, @@ -106,7 +120,9 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er tx.UsedBinaries, tx.UsedSteps, tx.ReceivedAt, - fromAddress); err != nil { + fromAddress, + tx.IsWIP, + tx.IP); err != nil { return err } return nil @@ -115,18 +131,51 @@ func (p *PostgresPoolStorage) AddTx(ctx context.Context, tx pool.Transaction) er // GetTxsByStatus returns an array of transactions filtered by status // limit parameter is used to limit amount txs from the db, // if limit = 0, then there is no limit -func (p *PostgresPoolStorage) GetTxsByStatus(ctx context.Context, status pool.TxStatus, isClaims bool, limit uint64) ([]pool.Transaction, error) { +func (p *PostgresPoolStorage) GetTxsByStatus(ctx context.Context, status pool.TxStatus, limit uint64) ([]pool.Transaction, error) { + var ( + rows pgx.Rows + err error + sql string + ) + if limit == 0 { + sql = "SELECT encoded, status, received_at, is_wip, ip, failed_reason FROM pool.transaction WHERE status = $1 ORDER BY gas_price DESC" + rows, err = p.db.Query(ctx, sql, status.String()) + } else { + sql = "SELECT encoded, status, received_at, is_wip, ip, failed_reason FROM pool.transaction WHERE status = $1 ORDER BY gas_price DESC LIMIT $2" + rows, err = p.db.Query(ctx, sql, status.String(), limit) + } + if err != nil { + return nil, err + } + defer rows.Close() + + txs := make([]pool.Transaction, 0, len(rows.RawValues())) + for rows.Next() { + tx, err := scanTx(rows) + if err != nil { + return nil, err + } + txs = append(txs, *tx) + } + + return txs, nil +} + +// GetNonWIPTxsByStatus returns an array of transactions filtered by status +// limit parameter is used to limit amount txs from the db, +// if limit = 0, then there is no limit +func (p *PostgresPoolStorage) GetNonWIPTxsByStatus(ctx context.Context, status pool.TxStatus, limit uint64) ([]pool.Transaction, error) { var ( rows pgx.Rows err error sql string ) if limit == 0 { - sql = "SELECT encoded, status, received_at FROM pool.txs WHERE status = $1 ORDER BY gas_price DESC" + sql = "SELECT encoded, status, received_at, is_wip, ip, failed_reason FROM pool.transaction WHERE is_wip IS FALSE and status = $1 ORDER BY gas_price DESC" rows, err = p.db.Query(ctx, sql, status.String()) } else { - sql = "SELECT encoded, status, received_at FROM pool.txs WHERE status = $1 AND is_claims = $2 ORDER BY gas_price DESC LIMIT $3" - rows, err = p.db.Query(ctx, sql, status.String(), isClaims, limit) + sql = "SELECT encoded, status, received_at, is_wip, ip, failed_reason FROM pool.transaction WHERE is_wip IS FALSE and status = $1 ORDER BY gas_price DESC LIMIT $2" + rows, err = p.db.Query(ctx, sql, status.String(), limit) } if err != nil { return nil, err @@ -147,7 +196,7 @@ func (p *PostgresPoolStorage) GetTxsByStatus(ctx context.Context, status pool.Tx // GetPendingTxHashesSince returns the pending tx since the given time. func (p *PostgresPoolStorage) GetPendingTxHashesSince(ctx context.Context, since time.Time) ([]common.Hash, error) { - sql := "SELECT hash FROM pool.txs WHERE status = $1 AND received_at >= $2" + sql := "SELECT hash FROM pool.transaction WHERE status = $1 AND received_at >= $2" rows, err := p.db.Query(ctx, sql, pool.TxStatusPending, since) if err != nil { return nil, err @@ -167,7 +216,7 @@ func (p *PostgresPoolStorage) GetPendingTxHashesSince(ctx context.Context, since } // GetTxs gets txs with the lowest nonce -func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxStatus, isClaims bool, minGasPrice, limit uint64) ([]*pool.Transaction, error) { +func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxStatus, minGasPrice, limit uint64) ([]*pool.Transaction, error) { query := ` SELECT encoded, @@ -181,16 +230,17 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt used_binaries, used_steps, received_at, - nonce + nonce, + is_wip, + ip FROM - pool.txs p1 + pool.transaction p1 WHERE status = $1 AND - gas_price >= $2 AND - is_claims = $3 + gas_price >= $2 ORDER BY nonce ASC - LIMIT $4 + LIMIT $3 ` if filterStatus == pool.TxStatusFailed { @@ -208,36 +258,38 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt used_binaries, used_steps, received_at, - nonce + nonce, + is_wip, + ip FROM - pool.txs p1 + pool.transaction p1 WHERE status = $1 AND - gas_price >= $2 AND - is_claims = $3 + gas_price >= $2 ORDER BY - failed_counter ASC - LIMIT $4 + nonce ASC + LIMIT $3 ) as tmp ORDER BY nonce ASC ` } var ( - encoded, status string - receivedAt time.Time - cumulativeGasUsed int64 + encoded, status, ip string + receivedAt time.Time + cumulativeGasUsed uint64 usedKeccakHashes, usedPoseidonHashes, usedPoseidonPaddings, - usedMemAligns, usedArithmetics, usedBinaries, usedSteps int32 + usedMemAligns, usedArithmetics, usedBinaries, usedSteps uint32 nonce uint64 + isWIP bool ) - args := []interface{}{filterStatus, minGasPrice, isClaims, limit} + args := []interface{}{filterStatus, minGasPrice, limit} rows, err := p.db.Query(ctx, query, args...) if errors.Is(err, pgx.ErrNoRows) { - return nil, ErrNotFound + return nil, pool.ErrNotFound } else if err != nil { return nil, err } @@ -256,7 +308,10 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt &usedBinaries, &usedSteps, &receivedAt, - &nonce) + &nonce, + &isWIP, + &ip, + ) if err != nil { return nil, err @@ -272,7 +327,7 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt tx.Status = pool.TxStatus(status) tx.ReceivedAt = receivedAt - tx.ZkCounters = pool.ZkCounters{ + tx.ZKCounters = state.ZKCounters{ CumulativeGasUsed: cumulativeGasUsed, UsedKeccakHashes: usedKeccakHashes, UsedPoseidonHashes: usedPoseidonHashes, @@ -282,6 +337,8 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt UsedBinaries: usedBinaries, UsedSteps: usedSteps, } + tx.IsWIP = isWIP + tx.IP = ip txs = append(txs, tx) } @@ -292,7 +349,7 @@ func (p *PostgresPoolStorage) GetTxs(ctx context.Context, filterStatus pool.TxSt // CountTransactionsByStatus get number of transactions // accordingly to the provided status func (p *PostgresPoolStorage) CountTransactionsByStatus(ctx context.Context, status pool.TxStatus) (uint64, error) { - sql := "SELECT COUNT(*) FROM pool.txs WHERE status = $1" + sql := "SELECT COUNT(*) FROM pool.transaction WHERE status = $1" var counter uint64 err := p.db.QueryRow(ctx, sql, status.String()).Scan(&counter) if err != nil { @@ -303,31 +360,45 @@ func (p *PostgresPoolStorage) CountTransactionsByStatus(ctx context.Context, sta // UpdateTxStatus updates a transaction status accordingly to the // provided status and hash -func (p *PostgresPoolStorage) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus) error { - sql := "UPDATE pool.txs SET status = $1 WHERE hash = $2" - if _, err := p.db.Exec(ctx, sql, newStatus, hash.Hex()); err != nil { +func (p *PostgresPoolStorage) UpdateTxStatus(ctx context.Context, updateInfo pool.TxStatusUpdateInfo) error { + sql := "UPDATE pool.transaction SET status = $1, is_wip = $2" + args := []interface{}{updateInfo.NewStatus, updateInfo.IsWIP} + + if updateInfo.FailedReason != nil { + sql += ", failed_reason = $3" + args = append(args, *updateInfo.FailedReason) + sql += " WHERE hash = $4" + } else { + sql += " WHERE hash = $3" + } + + args = append(args, updateInfo.Hash.Hex()) + + if _, err := p.db.Exec(ctx, sql, args...); err != nil { return err } + return nil } // UpdateTxsStatus updates transactions status accordingly to the provided status and hashes -func (p *PostgresPoolStorage) UpdateTxsStatus(ctx context.Context, hashes []string, newStatus pool.TxStatus) error { - sql := "UPDATE pool.txs SET status = $1 WHERE hash = ANY ($2)" - if _, err := p.db.Exec(ctx, sql, newStatus, hashes); err != nil { - return err +func (p *PostgresPoolStorage) UpdateTxsStatus(ctx context.Context, updateInfos []pool.TxStatusUpdateInfo) error { + for _, updateInfo := range updateInfos { + if err := p.UpdateTxStatus(ctx, updateInfo); err != nil { + return err + } } return nil } -// DeleteTxsByHashes deletes txs by their hashes -func (p *PostgresPoolStorage) DeleteTxsByHashes(ctx context.Context, hashes []common.Hash) error { +// DeleteTransactionsByHashes deletes txs by their hashes +func (p *PostgresPoolStorage) DeleteTransactionsByHashes(ctx context.Context, hashes []common.Hash) error { hh := make([]string, 0, len(hashes)) for _, h := range hashes { hh = append(hh, h.Hex()) } - query := "DELETE FROM pool.txs WHERE hash = ANY ($1)" + query := "DELETE FROM pool.transaction WHERE hash = ANY ($1)" if _, err := p.db.Exec(ctx, query, hh); err != nil { return err } @@ -367,11 +438,25 @@ func (p *PostgresPoolStorage) GetGasPrice(ctx context.Context) (uint64, error) { return gasPrice, nil } +// MinGasPriceSince returns the min gas price after given timestamp +func (p *PostgresPoolStorage) MinGasPriceSince(ctx context.Context, timestamp time.Time) (uint64, error) { + sql := "SELECT COALESCE(MIN(price), 0) FROM pool.gas_price WHERE \"timestamp\" >= $1 LIMIT 1" + var gasPrice uint64 + err := p.db.QueryRow(ctx, sql, timestamp).Scan(&gasPrice) + if gasPrice == 0 || errors.Is(err, pgx.ErrNoRows) { + return 0, state.ErrNotFound + } else if err != nil { + return 0, err + } + + return gasPrice, nil +} + // IsTxPending determines if the tx associated to the given hash is pending or // not. func (p *PostgresPoolStorage) IsTxPending(ctx context.Context, hash common.Hash) (bool, error) { var exists bool - req := "SELECT exists (SELECT 1 FROM pool.txs WHERE hash = $1 AND status = $2)" + req := "SELECT exists (SELECT 1 FROM pool.transaction WHERE hash = $1 AND status = $2)" err := p.db.QueryRow(ctx, req, hash.Hex(), pool.TxStatusPending).Scan(&exists) if err != nil && err != sql.ErrNoRows { return false, err @@ -382,8 +467,8 @@ func (p *PostgresPoolStorage) IsTxPending(ctx context.Context, hash common.Hash) // GetTxsByFromAndNonce get all the transactions from the pool with the same from and nonce func (p *PostgresPoolStorage) GetTxsByFromAndNonce(ctx context.Context, from common.Address, nonce uint64) ([]pool.Transaction, error) { - sql := `SELECT encoded, status, received_at - FROM pool.txs + sql := `SELECT encoded, status, received_at, is_wip, ip, failed_reason + FROM pool.transaction WHERE from_address = $1 AND nonce = $2` rows, err := p.db.Query(ctx, sql, from.String(), nonce) @@ -409,7 +494,7 @@ func (p *PostgresPoolStorage) GetTxsByFromAndNonce(ctx context.Context, from com // GetTxFromAddressFromByHash gets tx from address by hash func (p *PostgresPoolStorage) GetTxFromAddressFromByHash(ctx context.Context, hash common.Hash) (common.Address, uint64, error) { query := `SELECT from_address, nonce - FROM pool.txs + FROM pool.transaction WHERE hash = $1 ` @@ -425,21 +510,12 @@ func (p *PostgresPoolStorage) GetTxFromAddressFromByHash(ctx context.Context, ha return common.HexToAddress(fromAddr), nonce, nil } -// IncrementFailedCounter increment for failed txs failed counter -func (p *PostgresPoolStorage) IncrementFailedCounter(ctx context.Context, hashes []string) error { - sql := "UPDATE pool.txs SET failed_counter = failed_counter + 1 WHERE hash = ANY ($1)" - if _, err := p.db.Exec(ctx, sql, hashes); err != nil { - return err - } - return nil -} - // GetNonce gets the nonce to the provided address accordingly to the txs in the pool func (p *PostgresPoolStorage) GetNonce(ctx context.Context, address common.Address) (uint64, error) { sql := `SELECT MAX(nonce) - FROM pool.txs + FROM pool.transaction WHERE from_address = $1 - AND (status = $2 OR status = $3)` + AND status IN ($2, $3)` rows, err := p.db.Query(ctx, sql, address.String(), pool.TxStatusPending, pool.TxStatusSelected) if errors.Is(err, pgx.ErrNoRows) { return 0, nil @@ -472,16 +548,17 @@ func (p *PostgresPoolStorage) GetNonce(ctx context.Context, address common.Addre // GetTxByHash gets a transaction in the pool by its hash func (p *PostgresPoolStorage) GetTxByHash(ctx context.Context, hash common.Hash) (*pool.Transaction, error) { var ( - encoded, status string - receivedAt time.Time + encoded, status, ip string + receivedAt time.Time + isWIP bool ) - sql := `SELECT encoded, status, received_at - FROM pool.txs + sql := `SELECT encoded, status, received_at, is_wip, ip + FROM pool.transaction WHERE hash = $1` - err := p.db.QueryRow(ctx, sql, hash.String()).Scan(&encoded, &status, &receivedAt) + err := p.db.QueryRow(ctx, sql, hash.String()).Scan(&encoded, &status, &receivedAt, &isWIP, &ip) if errors.Is(err, pgx.ErrNoRows) { - return nil, ErrNotFound + return nil, pool.ErrNotFound } else if err != nil { return nil, err } @@ -495,20 +572,27 @@ func (p *PostgresPoolStorage) GetTxByHash(ctx context.Context, hash common.Hash) if err := tx.UnmarshalBinary(b); err != nil { return nil, err } - return &pool.Transaction{ + + poolTx := &pool.Transaction{ ReceivedAt: receivedAt, Status: pool.TxStatus(status), Transaction: *tx, - }, nil + IsWIP: isWIP, + IP: ip, + } + + return poolTx, nil } func scanTx(rows pgx.Rows) (*pool.Transaction, error) { var ( - encoded, status string - receivedAt time.Time + encoded, status, ip string + receivedAt time.Time + isWIP bool + failedReason *string ) - if err := rows.Scan(&encoded, &status, &receivedAt); err != nil { + if err := rows.Scan(&encoded, &status, &receivedAt, &isWIP, &ip, &failedReason); err != nil { return nil, err } @@ -525,6 +609,82 @@ func scanTx(rows pgx.Rows) (*pool.Transaction, error) { tx.Status = pool.TxStatus(status) tx.ReceivedAt = receivedAt + tx.IsWIP = isWIP + tx.IP = ip + tx.FailedReason = failedReason return tx, nil } + +// DeleteTransactionByHash deletes tx by its hash +func (p *PostgresPoolStorage) DeleteTransactionByHash(ctx context.Context, hash common.Hash) error { + query := "DELETE FROM pool.transaction WHERE hash = $1" + if _, err := p.db.Exec(ctx, query, hash); err != nil { + return err + } + return nil +} + +// GetTxZkCountersByHash gets a transaction zkcounters by its hash +func (p *PostgresPoolStorage) GetTxZkCountersByHash(ctx context.Context, hash common.Hash) (*state.ZKCounters, error) { + var zkCounters state.ZKCounters + + sql := `SELECT cumulative_gas_used, used_keccak_hashes, used_poseidon_hashes, used_poseidon_paddings, used_mem_aligns, + used_arithmetics, used_binaries, used_steps FROM pool.transaction WHERE hash = $1` + err := p.db.QueryRow(ctx, sql, hash.String()).Scan(&zkCounters.CumulativeGasUsed, &zkCounters.UsedKeccakHashes, + &zkCounters.UsedPoseidonHashes, &zkCounters.UsedPoseidonPaddings, + &zkCounters.UsedMemAligns, &zkCounters.UsedArithmetics, &zkCounters.UsedBinaries, &zkCounters.UsedSteps) + if errors.Is(err, pgx.ErrNoRows) { + return nil, pool.ErrNotFound + } else if err != nil { + return nil, err + } + + return &zkCounters, nil +} + +// MarkWIPTxsAsPending updates WIP status to non WIP +func (p *PostgresPoolStorage) MarkWIPTxsAsPending(ctx context.Context) error { + const query = `UPDATE pool.transaction SET is_wip = false WHERE is_wip = true` + if _, err := p.db.Exec(ctx, query); err != nil { + return err + } + return nil +} + +// UpdateTxWIPStatus updates a transaction wip status accordingly to the +// provided WIP status and hash +func (p *PostgresPoolStorage) UpdateTxWIPStatus(ctx context.Context, hash common.Hash, isWIP bool) error { + sql := "UPDATE pool.transaction SET is_wip = $1 WHERE hash = $2" + if _, err := p.db.Exec(ctx, sql, isWIP, hash.Hex()); err != nil { + return err + } + return nil +} + +// GetAllAddressesBlocked get all addresses blocked +func (p *PostgresPoolStorage) GetAllAddressesBlocked(ctx context.Context) ([]common.Address, error) { + sql := `SELECT addr FROM pool.blocked` + + rows, err := p.db.Query(ctx, sql) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return nil, nil + } else { + return nil, err + } + } + defer rows.Close() + + var addrs []common.Address + for rows.Next() { + var addr string + err := rows.Scan(&addr) + if err != nil { + return nil, err + } + addrs = append(addrs, common.HexToAddress(addr)) + } + + return addrs, nil +} diff --git a/pool/pool.go b/pool/pool.go index 38a398b46f..0a3d77e3ed 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -5,32 +5,23 @@ import ( "errors" "fmt" "math/big" + "sync" "time" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" ) -const ( - // txSlotSize is used to calculate how many data slots a single transaction - // takes up based on its size. The slots are used as DoS protection, ensuring - // that validating a new transaction remains a constant operation (in reality - // O(maxslots), where max slots are 4 currently). - txSlotSize = 32 * 1024 - - // txMaxSize is the maximum size a single transaction can have. This field has - // non-trivial consequences: larger transactions are significantly harder and - // more expensive to propagate; larger transactions also take more resources - // to validate whether they fit into the pool or not. - txMaxSize = 4 * txSlotSize // 128KB - - // bridgeClaimMethodSignature for tracking bridgeClaimMethodSignature method - bridgeClaimMethodSignature = "0x25308c93" -) - var ( + // ErrNotFound indicates an object has not been found for the search criteria used + ErrNotFound = errors.New("object not found") + // ErrAlreadyKnown is returned if the transactions is already contained // within the pool. ErrAlreadyKnown = errors.New("already known") @@ -44,49 +35,185 @@ var ( // that uses a postgres database to store the data type Pool struct { storage - state stateInterface - l2BridgeAddr common.Address - chainID uint64 + state stateInterface + chainID uint64 + cfg Config + blockedAddresses sync.Map + minSuggestedGasPrice *big.Int + minSuggestedGasPriceMux *sync.RWMutex + eventLog *event.EventLog +} + +type preExecutionResponse struct { + usedZkCounters state.ZKCounters + isOOC bool + isOOG bool + isReverted bool } // NewPool creates and initializes an instance of Pool -func NewPool(s storage, st stateInterface, l2BridgeAddr common.Address, chainID uint64) *Pool { - return &Pool{ - storage: s, - state: st, - l2BridgeAddr: l2BridgeAddr, - chainID: chainID, +func NewPool(cfg Config, s storage, st stateInterface, l2BridgeAddr common.Address, chainID uint64, eventLog *event.EventLog) *Pool { + p := &Pool{ + cfg: cfg, + storage: s, + state: st, + chainID: chainID, + blockedAddresses: sync.Map{}, + minSuggestedGasPriceMux: new(sync.RWMutex), + eventLog: eventLog, } + + p.refreshBlockedAddresses() + go func(cfg *Config, p *Pool) { + for { + time.Sleep(cfg.IntervalToRefreshBlockedAddresses.Duration) + p.refreshBlockedAddresses() + } + }(&cfg, p) + return p +} + +// refreshBlockedAddresses refreshes the list of blocked addresses for the provided instance of pool +func (p *Pool) refreshBlockedAddresses() { + blockedAddresses, err := p.storage.GetAllAddressesBlocked(context.Background()) + if err != nil { + log.Error("failed to load blocked addresses") + return + } + + blockedAddressesMap := sync.Map{} + for _, blockedAddress := range blockedAddresses { + blockedAddressesMap.Store(blockedAddress.String(), 1) + p.blockedAddresses.Store(blockedAddress.String(), 1) + } + + unblockedAddresses := []string{} + p.blockedAddresses.Range(func(key, value any) bool { + addrHex := key.(string) + _, found := blockedAddressesMap.Load(addrHex) + if found { + return true + } + + unblockedAddresses = append(unblockedAddresses, addrHex) + return true + }) + + for _, unblockedAddress := range unblockedAddresses { + p.blockedAddresses.Delete(unblockedAddress) + } +} + +// StartPollingMinSuggestedGasPrice starts polling the minimum suggested gas price +func (p *Pool) StartPollingMinSuggestedGasPrice(ctx context.Context) { + p.pollMinSuggestedGasPrice(ctx) + go func() { + for { + select { + case <-ctx.Done(): + return + case <-time.After(p.cfg.PollMinAllowedGasPriceInterval.Duration): + p.pollMinSuggestedGasPrice(ctx) + } + } + }() } // AddTx adds a transaction to the pool with the pending state -func (p *Pool) AddTx(ctx context.Context, tx types.Transaction) error { - if err := p.validateTx(ctx, tx); err != nil { +func (p *Pool) AddTx(ctx context.Context, tx types.Transaction, ip string) error { + poolTx := NewTransaction(tx, ip, false, p) + if err := p.validateTx(ctx, *poolTx); err != nil { return err } - poolTx := Transaction{ - Transaction: tx, - Status: TxStatusPending, - IsClaims: false, - ReceivedAt: time.Now(), + return p.StoreTx(ctx, tx, ip, false) +} + +// StoreTx adds a transaction to the pool with the pending state +func (p *Pool) StoreTx(ctx context.Context, tx types.Transaction, ip string, isWIP bool) error { + poolTx := NewTransaction(tx, ip, isWIP, p) + // Execute transaction to calculate its zkCounters + preExecutionResponse, err := p.PreExecuteTx(ctx, tx) + if err != nil { + log.Debugf("PreExecuteTx error (this can be ignored): %v", err) } - poolTx.IsClaims = poolTx.IsClaimTx(p.l2BridgeAddr) + if preExecutionResponse.isOOC { + event := &event.Event{ + ReceivedAt: time.Now(), + IPAddress: ip, + Source: event.Source_Node, + Component: event.Component_Pool, + Level: event.Level_Warning, + EventID: event.EventID_PreexecutionOOC, + Description: tx.Hash().String(), + } + + err := p.eventLog.LogEvent(ctx, event) + if err != nil { + log.Errorf("Error adding event: %v", err) + } + // Do not add tx to the pool + return fmt.Errorf("out of counters") + } else if preExecutionResponse.isOOG { + event := &event.Event{ + ReceivedAt: time.Now(), + IPAddress: ip, + Source: event.Source_Node, + Component: event.Component_Pool, + Level: event.Level_Warning, + EventID: event.EventID_PreexecutionOOG, + Description: tx.Hash().String(), + } + + err := p.eventLog.LogEvent(ctx, event) + if err != nil { + log.Errorf("Error adding event: %v", err) + } + } - return p.storage.AddTx(ctx, poolTx) + poolTx.ZKCounters = preExecutionResponse.usedZkCounters + + return p.storage.AddTx(ctx, *poolTx) +} + +// PreExecuteTx executes a transaction to calculate its zkCounters +func (p *Pool) PreExecuteTx(ctx context.Context, tx types.Transaction) (preExecutionResponse, error) { + response := preExecutionResponse{usedZkCounters: state.ZKCounters{}, isOOC: false, isOOG: false, isReverted: false} + + processBatchResponse, err := p.state.PreProcessTransaction(ctx, &tx, nil) + if err != nil { + return response, err + } + + if processBatchResponse.Responses != nil && len(processBatchResponse.Responses) > 0 { + errorToCheck := processBatchResponse.Responses[0].RomError + response.isReverted = errors.Is(errorToCheck, runtime.ErrExecutionReverted) + response.isOOC = executor.IsROMOutOfCountersError(executor.RomErrorCode(errorToCheck)) + response.isOOG = errors.Is(errorToCheck, runtime.ErrOutOfGas) + response.usedZkCounters = processBatchResponse.UsedZkCounters + } + + return response, nil } // GetPendingTxs from the pool // limit parameter is used to limit amount of pending txs from the db, // if limit = 0, then there is no limit -func (p *Pool) GetPendingTxs(ctx context.Context, isClaims bool, limit uint64) ([]Transaction, error) { - return p.storage.GetTxsByStatus(ctx, TxStatusPending, isClaims, limit) +func (p *Pool) GetPendingTxs(ctx context.Context, limit uint64) ([]Transaction, error) { + return p.storage.GetTxsByStatus(ctx, TxStatusPending, limit) +} + +// GetNonWIPPendingTxs from the pool +// limit parameter is used to limit amount of pending txs from the db, +// if limit = 0, then there is no limit +func (p *Pool) GetNonWIPPendingTxs(ctx context.Context, limit uint64) ([]Transaction, error) { + return p.storage.GetNonWIPTxsByStatus(ctx, TxStatusPending, limit) } // GetSelectedTxs gets selected txs from the pool db func (p *Pool) GetSelectedTxs(ctx context.Context, limit uint64) ([]Transaction, error) { - return p.storage.GetTxsByStatus(ctx, TxStatusSelected, false, limit) + return p.storage.GetTxsByStatus(ctx, TxStatusSelected, limit) } // GetPendingTxHashesSince returns the hashes of pending tx since the given date. @@ -96,8 +223,13 @@ func (p *Pool) GetPendingTxHashesSince(ctx context.Context, since time.Time) ([] // UpdateTxStatus updates a transaction state accordingly to the // provided state and hash -func (p *Pool) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus TxStatus) error { - return p.storage.UpdateTxStatus(ctx, hash, newStatus) +func (p *Pool) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus TxStatus, isWIP bool, failedReason *string) error { + return p.storage.UpdateTxStatus(ctx, TxStatusUpdateInfo{ + Hash: hash, + NewStatus: newStatus, + IsWIP: isWIP, + FailedReason: failedReason, + }) } // SetGasPrice allows an external component to define the gas price @@ -121,62 +253,88 @@ func (p *Pool) IsTxPending(ctx context.Context, hash common.Hash) (bool, error) return p.storage.IsTxPending(ctx, hash) } -func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error { +func (p *Pool) validateTx(ctx context.Context, poolTx Transaction) error { // check chain id - if tx.ChainId().Uint64() != p.chainID { + txChainID := poolTx.ChainId().Uint64() + if txChainID != p.chainID && txChainID != 0 { return ErrInvalidChainID } // Accept only legacy transactions until EIP-2718/2930 activates. - if tx.Type() != types.LegacyTxType { + if poolTx.Type() != types.LegacyTxType { return ErrTxTypeNotSupported } + // Reject transactions over defined size to prevent DOS attacks - if uint64(tx.Size()) > txMaxSize { + if poolTx.Size() > p.cfg.MaxTxBytesSize { return ErrOversizedData } + + // Reject transactions with a gas price lower than the minimum gas price + p.minSuggestedGasPriceMux.RLock() + gasPriceCmp := poolTx.GasPrice().Cmp(p.minSuggestedGasPrice) + p.minSuggestedGasPriceMux.RUnlock() + if gasPriceCmp == -1 { + return ErrGasPrice + } + // Transactions can't be negative. This may never happen using RLP decoded // transactions but may occur if you create a transaction using the RPC. - if tx.Value().Sign() < 0 { + if poolTx.Value().Sign() < 0 { return ErrNegativeValue } // Make sure the transaction is signed properly. - if err := state.CheckSignature(tx); err != nil { + if err := state.CheckSignature(poolTx.Transaction); err != nil { return ErrInvalidSender } - from, err := state.GetSender(tx) + from, err := state.GetSender(poolTx.Transaction) if err != nil { return ErrInvalidSender } - lastL2BlockNumber, err := p.state.GetLastL2BlockNumber(ctx, nil) + // check if sender is blocked + _, blocked := p.blockedAddresses.Load(from.String()) + if blocked { + return ErrBlockedSender + } + + lastL2Block, err := p.state.GetLastL2Block(ctx, nil) if err != nil { return err } - nonce, err := p.state.GetNonce(ctx, from, lastL2BlockNumber, nil) + nonce, err := p.state.GetNonce(ctx, from, lastL2Block.Root()) if err != nil { return err } // Ensure the transaction adheres to nonce ordering - if nonce > tx.Nonce() { + if nonce > poolTx.Nonce() { return ErrNonceTooLow } // Transactor should have enough funds to cover the costs // cost == V + GP * GL - balance, err := p.state.GetBalance(ctx, from, lastL2BlockNumber, nil) + balance, err := p.state.GetBalance(ctx, from, lastL2Block.Root()) if err != nil { return err } - if balance.Cmp(tx.Cost()) < 0 { + if balance.Cmp(poolTx.Cost()) < 0 { return ErrInsufficientFunds } + // Ensure the transaction has more gas than the basic poolTx fee. + intrGas, err := IntrinsicGas(poolTx.Transaction) + if err != nil { + return err + } + if poolTx.Gas() < intrGas { + return ErrIntrinsicGas + } + // try to get a transaction from the pool with the same nonce to check // if the new one has a price bump - oldTxs, err := p.storage.GetTxsByFromAndNonce(ctx, from, tx.Nonce()) + oldTxs, err := p.storage.GetTxsByFromAndNonce(ctx, from, poolTx.Nonce()) if err != nil { return err } @@ -185,27 +343,56 @@ func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error { // with the same from and nonce to be able to replace the current txs by the new // when being selected for _, oldTx := range oldTxs { + // discard invalid txs + if oldTx.Status == TxStatusInvalid || oldTx.Status == TxStatusFailed { + continue + } + oldTxPrice := new(big.Int).Mul(oldTx.GasPrice(), new(big.Int).SetUint64(oldTx.Gas())) - txPrice := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) + txPrice := new(big.Int).Mul(poolTx.GasPrice(), new(big.Int).SetUint64(poolTx.Gas())) - if oldTx.Hash() == tx.Hash() { + if oldTx.Hash() == poolTx.Hash() { return ErrAlreadyKnown } - // if old Tx Price is higher than the new tx price, it returns an error + // if old Tx Price is higher than the new poolTx price, it returns an error if oldTxPrice.Cmp(txPrice) > 0 { return ErrReplaceUnderpriced } } // Executor field size requirements check - if err := p.checkTxFieldCompatibilityWithExecutor(ctx, tx); err != nil { + if err := p.checkTxFieldCompatibilityWithExecutor(ctx, poolTx.Transaction); err != nil { return err } return nil } +func (p *Pool) pollMinSuggestedGasPrice(ctx context.Context) { + fromTimestamp := time.Now().UTC().Add(-p.cfg.MinAllowedGasPriceInterval.Duration) + gasPrice, err := p.storage.MinGasPriceSince(ctx, fromTimestamp) + if err != nil { + p.minSuggestedGasPriceMux.Lock() + // Ensuring we always have suggested minimum gas price + if p.minSuggestedGasPrice == nil { + p.minSuggestedGasPrice = big.NewInt(0).SetUint64(p.cfg.DefaultMinGasPriceAllowed) + log.Infof("Min allowed gas price updated to: %d", p.cfg.DefaultMinGasPriceAllowed) + } + p.minSuggestedGasPriceMux.Unlock() + if err == state.ErrNotFound { + log.Warnf("No suggested min gas price since: %v", fromTimestamp) + } else { + log.Errorf("Error getting min gas price since: %v", fromTimestamp) + } + } else { + p.minSuggestedGasPriceMux.Lock() + p.minSuggestedGasPrice = big.NewInt(0).SetUint64(gasPrice) + p.minSuggestedGasPriceMux.Unlock() + log.Infof("Min allowed gas price updated to: %d", gasPrice) + } +} + // checkTxFieldCompatibilityWithExecutor checks the field sizes of the transaction to make sure // they ar compatible with the Executor needs // GasLimit: 256 bits @@ -218,8 +405,6 @@ func (p *Pool) validateTx(ctx context.Context, tx types.Transaction) error { func (p *Pool) checkTxFieldCompatibilityWithExecutor(ctx context.Context, tx types.Transaction) error { maxUint64BigInt := big.NewInt(0).SetUint64(math.MaxUint64) - const maxDataSize = 30000 - // GasLimit, Nonce and To fields are limited by their types, no need to check // Gas Price and Value are checked against the balance, and the max balance allowed // by the merkletree service is uint256, in this case, if the transaction has a @@ -227,8 +412,8 @@ func (p *Pool) checkTxFieldCompatibilityWithExecutor(ctx context.Context, tx typ // reject the transaction dataSize := len(tx.Data()) - if dataSize > maxDataSize { - return fmt.Errorf("data size bigger than allowed, current size is %v bytes and max allowed is %v bytes", dataSize, maxDataSize) + if dataSize > p.cfg.MaxTxDataBytesSize { + return fmt.Errorf("data size bigger than allowed, current size is %v bytes and max allowed is %v bytes", dataSize, p.cfg.MaxTxDataBytesSize) } if tx.ChainId().Cmp(maxUint64BigInt) == 1 { @@ -238,31 +423,61 @@ func (p *Pool) checkTxFieldCompatibilityWithExecutor(ctx context.Context, tx typ return nil } -// MarkReorgedTxsAsPending updated reorged txs status from selected to pending -func (p *Pool) MarkReorgedTxsAsPending(ctx context.Context) error { - // get selected transactions from pool - selectedTxs, err := p.GetSelectedTxs(ctx, 0) - if err != nil { - return err - } +// DeleteReorgedTransactions deletes transactions from the pool +func (p *Pool) DeleteReorgedTransactions(ctx context.Context, transactions []*types.Transaction) error { + hashes := []common.Hash{} - txsHashesToUpdate := []string{} - // look for non existent transactions on state - for _, selectedTx := range selectedTxs { - txHash := selectedTx.Hash() - _, err := p.state.GetTransactionByHash(ctx, txHash, nil) - if errors.Is(err, state.ErrNotFound) { - txsHashesToUpdate = append(txsHashesToUpdate, txHash.String()) - } else if err != nil { - return err - } + for _, tx := range transactions { + hashes = append(hashes, tx.Hash()) } - // revert pool state from selected to pending on the pool - err = p.UpdateTxsStatus(ctx, txsHashesToUpdate, TxStatusPending) - if err != nil { - return err + return p.storage.DeleteTransactionsByHashes(ctx, hashes) +} + +// UpdateTxWIPStatus updates a transaction wip status accordingly to the +// provided WIP status and hash +func (p *Pool) UpdateTxWIPStatus(ctx context.Context, hash common.Hash, isWIP bool) error { + return p.storage.UpdateTxWIPStatus(ctx, hash, isWIP) +} + +const ( + txDataNonZeroGas uint64 = 16 + txGasContractCreation uint64 = 53000 + txGas uint64 = 21000 + txDataZeroGas uint64 = 4 +) + +// IntrinsicGas computes the 'intrinsic gas' for a given transaction. +func IntrinsicGas(tx types.Transaction) (uint64, error) { + // Set the starting gas for the raw transaction + var gas uint64 + if tx.To() == nil { + gas = txGasContractCreation + } else { + gas = txGas } + dataLen := uint64(len(tx.Data())) + // Bump the required gas by the amount of transactional data + if dataLen > 0 { + // Zero and non-zero bytes are priced differently + var nz uint64 + for _, byt := range tx.Data() { + if byt != 0 { + nz++ + } + } + // Make sure we don't exceed uint64 for all data combinations + nonZeroGas := txDataNonZeroGas + if (math.MaxUint64-gas)/nonZeroGas < nz { + return 0, ErrGasUintOverflow + } + gas += nz * nonZeroGas - return nil + z := dataLen - nz + if (math.MaxUint64-gas)/txDataZeroGas < z { + return 0, ErrGasUintOverflow + } + gas += z * txDataZeroGas + } + return gas, nil } diff --git a/pool/pool_test.go b/pool/pool_test.go index c5e1648967..d84a852cc2 100644 --- a/pool/pool_test.go +++ b/pool/pool_test.go @@ -11,8 +11,11 @@ import ( "testing" "time" + cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" "github.com/0xPolygonHermez/zkevm-node/db" "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" @@ -20,12 +23,13 @@ import ( "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Revert" "github.com/0xPolygonHermez/zkevm-node/test/dbutils" "github.com/0xPolygonHermez/zkevm-node/test/operations" "github.com/0xPolygonHermez/zkevm-node/test/testutils" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/jackc/pgx/v4/pgxpool" "github.com/stretchr/testify/assert" @@ -34,27 +38,42 @@ import ( const ( senderPrivateKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + senderAddress = "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D" +) + +var ( + l2BridgeAddr = common.HexToAddress("0x00000000000000000000000000000001") ) var ( stateDBCfg = dbutils.NewStateConfigFromEnv() poolDBCfg = dbutils.NewPoolConfigFromEnv() genesis = state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { - Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + Address: senderAddress, Type: int(merkletree.LeafTypeBalance), - Value: "1000000000000000000000", + Value: "90000000000000000000000000000000000000000000000000000000000", }, }, } - chainID = big.NewInt(1337) + cfg = pool.Config{ + MaxTxBytesSize: 30132, + MaxTxDataBytesSize: 30000, + MinAllowedGasPriceInterval: cfgTypes.NewDuration(5 * time.Minute), + PollMinAllowedGasPriceInterval: cfgTypes.NewDuration(15 * time.Second), + DefaultMinGasPriceAllowed: 1000000000, + IntervalToRefreshBlockedAddresses: cfgTypes.NewDuration(5 * time.Minute), + } + gasPrice = big.NewInt(1000000000) + gasLimit = uint64(21000) + chainID = big.NewInt(1337) ) func TestMain(m *testing.M) { log.Init(log.Config{ Level: "debug", - Outputs: []string{"stdout"}, + Outputs: []string{"stderr"}, }) code := m.Run() @@ -62,21 +81,24 @@ func TestMain(m *testing.M) { } func Test_AddTx(t *testing.T) { - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - panic(err) - } + require.NoError(t, err) defer stateSqlDB.Close() //nolint:gosec,errcheck poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer poolSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -84,15 +106,6 @@ func Test_AddTx(t *testing.T) { ParentHash: state.ZeroHash, ReceivedAt: time.Now(), } - genesis := state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0xb48cA794d49EeC406A5dD2c547717e37b5952a83", - Type: int(merkletree.LeafTypeBalance), - Value: "1000000000000000000000", - }, - }, - } ctx := context.Background() dbTx, err := st.BeginStateTransaction(ctx) require.NoError(t, err) @@ -101,61 +114,63 @@ func Test_AddTx(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) const chainID = 2576980377 - p := pool.NewPool(s, st, common.Address{}, chainID) + p := setupPool(t, cfg, s, st, chainID, ctx, eventLog) - txRLPHash := "0xf86e8212658082520894fd8b27a263e19f0e9592180e61f0f8c9dfeb1ff6880de0b6b3a764000080850133333355a01eac4c2defc7ed767ae36bbd02613c581b8fb87d0e4f579c9ee3a7cfdb16faa7a043ce30f43d952b9d034cf8f04fecb631192a5dbc7ee2a47f1f49c0d022a8849d" - b, err := hex.DecodeHex(txRLPHash) - if err != nil { - t.Error(err) - } - tx := new(types.Transaction) + tx := new(ethTypes.Transaction) + expectedTxEncoded := "0xf86880843b9aca008252089400000000000000000000000000000000000000008080850133333355a03ee24709870c8dbc67884c9c8acb864c1aceaaa7332b9a3db0d7a5d7c68eb8e4a0302980b070f5e3ffca3dc27b07daf69d66ab27d4df648e0b3ed059cf23aa168d" + b, err := hex.DecodeHex(expectedTxEncoded) + require.NoError(t, err) tx.UnmarshalBinary(b) //nolint:gosec,errcheck - err = p.AddTx(ctx, *tx) - if err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *tx, "") + require.NoError(t, err) - rows, err := poolSqlDB.Query(ctx, "SELECT hash, encoded, decoded, status FROM pool.txs") + rows, err := poolSqlDB.Query(ctx, "SELECT hash, encoded, decoded, status, used_steps FROM pool.transaction") + require.NoError(t, err) defer rows.Close() // nolint:staticcheck - if err != nil { - t.Error(err) - } c := 0 for rows.Next() { var hash, encoded, decoded, status string - err := rows.Scan(&hash, &encoded, &decoded, &status) - if err != nil { - t.Error(err) - } + var usedSteps int + err := rows.Scan(&hash, &encoded, &decoded, &status, &usedSteps) + require.NoError(t, err) b, _ := tx.MarshalJSON() - assert.Equal(t, "0xa3cff5abdf47d4feb8204a45c0a8c58fc9b9bb9b29c6588c1d206b746815e9cc", hash, "invalid hash") - assert.Equal(t, txRLPHash, encoded, "invalid encoded") + assert.Equal(t, "0x3c499a6308dbf4e67bd4e949b0b609e3a0a5a7fd6a497acb23e37ae7f0a923cc", hash, "invalid hash") + assert.Equal(t, expectedTxEncoded, encoded, "invalid encoded") assert.JSONEq(t, string(b), decoded, "invalid decoded") assert.Equal(t, string(pool.TxStatusPending), status, "invalid tx status") + assert.Greater(t, usedSteps, 0, "invalid used steps") c++ } assert.Equal(t, 1, c, "invalid number of txs in the pool") } -func Test_GetPendingTxs(t *testing.T) { - initOrResetDB() +func Test_AddTx_OversizedData(t *testing.T) { + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) if err != nil { - t.Error(err) + panic(err) } defer stateSqlDB.Close() //nolint:gosec,errcheck - st := newState(stateSqlDB) + poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + log.Fatal(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -163,6 +178,15 @@ func Test_GetPendingTxs(t *testing.T) { ParentHash: state.ZeroHash, ReceivedAt: time.Now(), } + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: senderAddress, + Type: int(merkletree.LeafTypeBalance), + Value: "1000000000000000000000", + }, + }, + } ctx := context.Background() dbTx, err := st.BeginStateTransaction(ctx) require.NoError(t, err) @@ -171,53 +195,128 @@ func Test_GetPendingTxs(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) + require.NoError(t, err) + + const chainID = 2576980377 + p := pool.NewPool(cfg, s, st, common.Address{}, chainID, eventLog) + + b := make([]byte, cfg.MaxTxBytesSize+1) + to := common.HexToAddress(operations.DefaultSequencerAddress) + tx := ethTypes.NewTransaction(0, to, big.NewInt(0), gasLimit, big.NewInt(0), b) + + // GetAuth configures and returns an auth object. + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, chainID) + require.NoError(t, err) + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + + err = p.AddTx(ctx, *signedTx, "") + require.EqualError(t, err, pool.ErrOversizedData.Error()) +} + +func Test_AddPreEIP155Tx(t *testing.T) { + initOrResetDB(t) + + stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } + eventLog := event.NewEventLog(event.Config{}, eventStorage) - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + st := newState(stateSqlDB, eventLog) - const txsCount = 10 - const limit = 5 + genesisBlock := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: senderAddress, + Type: int(merkletree.LeafTypeBalance), + Value: "1000000000000000000000", + }, + { + Address: "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + Type: int(merkletree.LeafTypeBalance), + Value: "200000000000000000000", + }, + }, + } + ctx := context.Background() + dbTx, err := st.BeginStateTransaction(ctx) + require.NoError(t, err) + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) + s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) require.NoError(t, err) - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + const chainID = 2576980377 + p := setupPool(t, cfg, s, st, chainID, ctx, eventLog) + + batchL2Data := "0xe580843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae98808464fbb77c6b39bdc5f8e458aba689f2a1ff8c543a94e4817bda40f3fe34080c4ab26c1e3c2fc2cda93bc32f0a79940501fd505dcf48d94abfde932ebf1417f502cb0d9de81b" + b, err := hex.DecodeHex(batchL2Data) + require.NoError(t, err) + txs, _, err := state.DecodeTxs(b) require.NoError(t, err) - // insert pending transactions - for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - signedTx, err := auth.Signer(auth.From, tx) + tx := txs[0] + + err = p.AddTx(ctx, tx, "") + require.NoError(t, err) + + rows, err := poolSqlDB.Query(ctx, "SELECT hash, encoded, decoded, status FROM pool.transaction") + require.NoError(t, err) + defer rows.Close() // nolint:staticcheck + + c := 0 + for rows.Next() { + var hash, encoded, decoded, status string + err := rows.Scan(&hash, &encoded, &decoded, &status) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx); err != nil { - t.Error(err) - } - } - txs, err := p.GetPendingTxs(ctx, false, limit) - if err != nil { - t.Error(err) - } + b, err := tx.MarshalBinary() + require.NoError(t, err) - assert.Equal(t, limit, len(txs)) + bJSON, err := tx.MarshalJSON() + require.NoError(t, err) - for i := 0; i < txsCount; i++ { - assert.Equal(t, pool.TxStatusPending, txs[0].Status) + assert.Equal(t, tx.Hash().String(), hash, "invalid hash") + assert.Equal(t, hex.EncodeToHex(b), encoded, "invalid encoded") + assert.JSONEq(t, string(bJSON), decoded, "invalid decoded") + assert.Equal(t, string(pool.TxStatusPending), status, "invalid tx status") + c++ } + + assert.Equal(t, 1, c, "invalid number of txs in the pool") } -func Test_GetPendingTxsZeroPassed(t *testing.T) { - initOrResetDB() +func Test_GetPendingTxs(t *testing.T) { + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer stateSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -233,14 +332,11 @@ func Test_GetPendingTxsZeroPassed(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) const txsCount = 10 - const limit = 0 + const limit = 5 privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) @@ -250,37 +346,37 @@ func Test_GetPendingTxsZeroPassed(t *testing.T) { // insert pending transactions for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx := ethTypes.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) } - txs, err := p.GetPendingTxs(ctx, false, limit) - if err != nil { - t.Error(err) - } + txs, err := p.GetPendingTxs(ctx, limit) + require.NoError(t, err) - assert.Equal(t, txsCount, len(txs)) + assert.Equal(t, limit, len(txs)) for i := 0; i < txsCount; i++ { assert.Equal(t, pool.TxStatusPending, txs[0].Status) } } -func Test_GetTopPendingTxByProfitabilityAndZkCounters(t *testing.T) { - ctx := context.Background() - initOrResetDB() +func Test_GetPendingTxsZeroPassed(t *testing.T) { + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer stateSqlDB.Close() + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -288,6 +384,7 @@ func Test_GetTopPendingTxByProfitabilityAndZkCounters(t *testing.T) { ParentHash: state.ZeroHash, ReceivedAt: time.Now(), } + ctx := context.Background() dbTx, err := st.BeginStateTransaction(ctx) require.NoError(t, err) _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) @@ -295,13 +392,11 @@ func Test_GetTopPendingTxByProfitabilityAndZkCounters(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) const txsCount = 10 + const limit = 0 privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) @@ -311,31 +406,38 @@ func Test_GetTopPendingTxByProfitabilityAndZkCounters(t *testing.T) { // insert pending transactions for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(i)), []byte{}) + tx := ethTypes.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) } - txs, err := p.GetTxs(ctx, pool.TxStatusPending, false, 1, 10) + txs, err := p.GetPendingTxs(ctx, limit) require.NoError(t, err) - // bcs it's sorted by nonce, tx with the lowest nonce is expected here - assert.Equal(t, txs[0].Transaction.Nonce(), uint64(0)) + + assert.Equal(t, txsCount, len(txs)) + + for i := 0; i < txsCount; i++ { + assert.Equal(t, pool.TxStatusPending, txs[0].Status) + } } -func Test_GetTopFailedTxsByProfitabilityAndZkCounters(t *testing.T) { +func Test_GetTopPendingTxByProfitabilityAndZkCounters(t *testing.T) { ctx := context.Background() - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer stateSqlDB.Close() + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -350,11 +452,8 @@ func Test_GetTopFailedTxsByProfitabilityAndZkCounters(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) const txsCount = 10 @@ -364,46 +463,41 @@ func Test_GetTopFailedTxsByProfitabilityAndZkCounters(t *testing.T) { auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) require.NoError(t, err) - txsHashes := make([]string, 0, txsCount) // insert pending transactions for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(i)), []byte{}) + tx := ethTypes.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), gasLimit, big.NewInt(gasPrice.Int64()+int64(i)), []byte{}) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx); err != nil { - t.Error(err) - } - txsHashes = append(txsHashes, signedTx.Hash().String()) + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) } - err = p.UpdateTxsStatus(ctx, txsHashes, pool.TxStatusFailed) - require.NoError(t, err) - err = p.IncrementFailedCounter(ctx, txsHashes[0:txsCount/2]) - require.NoError(t, err) - txs, err := p.GetTxs(ctx, pool.TxStatusFailed, false, 1, 10) + txs, err := p.GetTxs(ctx, pool.TxStatusPending, 1, 10) require.NoError(t, err) // bcs it's sorted by nonce, tx with the lowest nonce is expected here - assert.Equal(t, txsCount, len(txs)) + assert.Equal(t, txs[0].Transaction.Nonce(), uint64(0)) } func Test_UpdateTxsStatus(t *testing.T) { ctx := context.Background() - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer stateSqlDB.Close() //nolint:gosec,errcheck poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer poolSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -418,11 +512,8 @@ func Test_UpdateTxsStatus(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) @@ -430,51 +521,74 @@ func Test_UpdateTxsStatus(t *testing.T) { auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) require.NoError(t, err) - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx1 := ethTypes.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx1, err := auth.Signer(auth.From, tx1) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx1); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx1, "") + require.NoError(t, err) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx2 := ethTypes.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx2, err := auth.Signer(auth.From, tx2) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx2); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx2, "") + require.NoError(t, err) - err = p.UpdateTxsStatus(ctx, []string{signedTx1.Hash().String(), signedTx2.Hash().String()}, pool.TxStatusInvalid) + expectedFailedReason := "failed" + newStatus := pool.TxStatusInvalid + err = p.UpdateTxsStatus(ctx, []pool.TxStatusUpdateInfo{ + { + Hash: signedTx1.Hash(), + NewStatus: newStatus, + IsWIP: false, + FailedReason: &expectedFailedReason, + }, + { + Hash: signedTx2.Hash(), + NewStatus: newStatus, + IsWIP: false, + FailedReason: &expectedFailedReason, + }, + }) if err != nil { t.Error(err) } var count int - err = poolSqlDB.QueryRow(ctx, "SELECT COUNT(*) FROM pool.txs WHERE status = $1", pool.TxStatusInvalid).Scan(&count) + rows, err := poolSqlDB.Query(ctx, "SELECT status, failed_reason FROM pool.transaction WHERE hash = ANY($1)", []string{signedTx1.Hash().String(), signedTx2.Hash().String()}) + defer rows.Close() // nolint:staticcheck if err != nil { t.Error(err) } + var state, failedReason string + for rows.Next() { + count++ + if err := rows.Scan(&state, &failedReason); err != nil { + t.Error(err) + } + } assert.Equal(t, 2, count) } func Test_UpdateTxStatus(t *testing.T) { ctx := context.Background() - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer stateSqlDB.Close() //nolint:gosec,errcheck poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer poolSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -489,149 +603,81 @@ func Test_UpdateTxStatus(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) require.NoError(t, err) - - tx := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx := ethTypes.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx); err != nil { + if err := p.AddTx(ctx, *signedTx, ""); err != nil { t.Error(err) } - - err = p.UpdateTxStatus(ctx, signedTx.Hash(), pool.TxStatusInvalid) + expectedFailedReason := "failed" + err = p.UpdateTxStatus(ctx, signedTx.Hash(), pool.TxStatusInvalid, false, &expectedFailedReason) if err != nil { t.Error(err) } - rows, err := poolSqlDB.Query(ctx, "SELECT status FROM pool.txs WHERE hash = $1", signedTx.Hash().Hex()) - defer rows.Close() // nolint:staticcheck - if err != nil { - t.Error(err) - } + rows, err := poolSqlDB.Query(ctx, "SELECT status, failed_reason FROM pool.transaction WHERE hash = $1", signedTx.Hash().Hex()) + require.NoError(t, err) - var state string + defer rows.Close() // nolint:staticcheck + var state, failedReason string rows.Next() - if err := rows.Scan(&state); err != nil { + if err := rows.Scan(&state, &failedReason); err != nil { t.Error(err) } assert.Equal(t, pool.TxStatusInvalid, pool.TxStatus(state)) + assert.Equal(t, expectedFailedReason, failedReason) } func Test_SetAndGetGasPrice(t *testing.T) { - initOrResetDB() + initOrResetDB(t) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) + + eventStorage, err := nileventstorage.NewNilEventStorage() + require.NoError(t, err) + eventLog := event.NewEventLog(event.Config{}, eventStorage) - p := pool.NewPool(s, nil, common.Address{}, chainID.Uint64()) + p := pool.NewPool(cfg, s, nil, common.Address{}, chainID.Uint64(), eventLog) nBig, err := rand.Int(rand.Reader, big.NewInt(0).SetUint64(math.MaxUint64)) - if err != nil { - t.Error(err) - } + require.NoError(t, err) expectedGasPrice := nBig.Uint64() ctx := context.Background() err = p.SetGasPrice(ctx, expectedGasPrice) - if err != nil { - t.Error(err) - } - - gasPrice, err := p.GetGasPrice(ctx) - if err != nil { - t.Error(err) - } - - assert.Equal(t, expectedGasPrice, gasPrice) -} - -func TestMarkReorgedTxsAsPending(t *testing.T) { - initOrResetDB() - ctx := context.Background() - stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - t.Error(err) - } - defer stateSqlDB.Close() //nolint:gosec,errcheck - - st := newState(stateSqlDB) - - genesisBlock := state.Block{ - BlockNumber: 0, - BlockHash: state.ZeroHash, - ParentHash: state.ZeroHash, - ReceivedAt: time.Now(), - } - dbTx, err := st.BeginStateTransaction(ctx) - require.NoError(t, err) - _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) - require.NoError(t, err) - require.NoError(t, dbTx.Commit(ctx)) - - s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) - - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) - require.NoError(t, err) - - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - signedTx1, err := auth.Signer(auth.From, tx1) - require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx1); err != nil { - t.Error(err) - } - - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - signedTx2, err := auth.Signer(auth.From, tx2) + gasPrice, err := p.GetGasPrice(ctx) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx2); err != nil { - t.Error(err) - } - - err = p.UpdateTxsStatus(ctx, []string{signedTx1.Hash().String(), signedTx2.Hash().String()}, pool.TxStatusSelected) - if err != nil { - t.Error(err) - } - err = p.MarkReorgedTxsAsPending(ctx) - require.NoError(t, err) - txs, err := p.GetPendingTxs(ctx, false, 100) - require.NoError(t, err) - require.Equal(t, signedTx1.Hash().Hex(), txs[1].Hash().Hex()) - require.Equal(t, signedTx2.Hash().Hex(), txs[0].Hash().Hex()) + assert.Equal(t, expectedGasPrice, gasPrice) } func TestGetPendingTxSince(t *testing.T) { - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer stateSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -647,11 +693,8 @@ func TestGetPendingTxSince(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) const txsCount = 10 @@ -667,30 +710,25 @@ func TestGetPendingTxSince(t *testing.T) { timeBeforeTxs := time.Now() // insert pending transactions for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx := ethTypes.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) txsAddedTime = append(txsAddedTime, time.Now()) - if err := p.AddTx(ctx, *signedTx); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) txsAddedHashes = append(txsAddedHashes, signedTx.Hash()) time.Sleep(1 * time.Second) } txHashes, err := p.GetPendingTxHashesSince(ctx, timeBeforeTxs) - if err != nil { - t.Error(err) - } + require.NoError(t, err) assert.Equal(t, txsCount, len(txHashes)) for i, txHash := range txHashes { assert.Equal(t, txHash.Hex(), txsAddedHashes[i].Hex()) } txHashes, err = p.GetPendingTxHashesSince(ctx, txsAddedTime[5]) - if err != nil { - t.Error(err) - } + require.NoError(t, err) assert.Equal(t, 5, len(txHashes)) assert.Equal(t, txHashes[0].Hex(), txsAddedHashes[5].Hex()) assert.Equal(t, txHashes[1].Hex(), txsAddedHashes[6].Hex()) @@ -699,43 +737,39 @@ func TestGetPendingTxSince(t *testing.T) { assert.Equal(t, txHashes[4].Hex(), txsAddedHashes[9].Hex()) txHashes, err = p.GetPendingTxHashesSince(ctx, txsAddedTime[8]) - if err != nil { - t.Error(err) - } + require.NoError(t, err) assert.Equal(t, 2, len(txHashes)) assert.Equal(t, txHashes[0].Hex(), txsAddedHashes[8].Hex()) assert.Equal(t, txHashes[1].Hex(), txsAddedHashes[9].Hex()) txHashes, err = p.GetPendingTxHashesSince(ctx, txsAddedTime[9]) - if err != nil { - t.Error(err) - } + require.NoError(t, err) assert.Equal(t, 1, len(txHashes)) assert.Equal(t, txHashes[0].Hex(), txsAddedHashes[9].Hex()) txHashes, err = p.GetPendingTxHashesSince(ctx, txsAddedTime[9].Add(1*time.Second)) - if err != nil { - t.Error(err) - } + require.NoError(t, err) assert.Equal(t, 0, len(txHashes)) } -func Test_DeleteTxsByHashes(t *testing.T) { +func Test_DeleteTransactionsByHashes(t *testing.T) { ctx := context.Background() - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) defer stateSqlDB.Close() //nolint:gosec,errcheck poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer poolSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -745,16 +779,14 @@ func Test_DeleteTxsByHashes(t *testing.T) { } dbTx, err := st.BeginStateTransaction(ctx) require.NoError(t, err) + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) require.NoError(t, err) require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) require.NoError(t, err) @@ -762,49 +794,45 @@ func Test_DeleteTxsByHashes(t *testing.T) { auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) require.NoError(t, err) - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx1 := ethTypes.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx1, err := auth.Signer(auth.From, tx1) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx1); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx1, "") + require.NoError(t, err) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) + tx2 := ethTypes.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), gasLimit, gasPrice, []byte{}) signedTx2, err := auth.Signer(auth.From, tx2) require.NoError(t, err) - if err := p.AddTx(ctx, *signedTx2); err != nil { - t.Error(err) - } + err = p.AddTx(ctx, *signedTx2, "") + require.NoError(t, err) - err = p.DeleteTxsByHashes(ctx, []common.Hash{signedTx1.Hash(), signedTx2.Hash()}) - if err != nil { - t.Error(err) - } + err = p.DeleteTransactionsByHashes(ctx, []common.Hash{signedTx1.Hash(), signedTx2.Hash()}) + require.NoError(t, err) var count int - err = poolSqlDB.QueryRow(ctx, "SELECT COUNT(*) FROM pool.txs").Scan(&count) - if err != nil { - t.Error(err) - } + err = poolSqlDB.QueryRow(ctx, "SELECT COUNT(*) FROM pool.transaction").Scan(&count) + require.NoError(t, err) assert.Equal(t, 0, count) } func Test_TryAddIncompatibleTxs(t *testing.T) { - initOrResetDB() + initOrResetDB(t) stateSqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - panic(err) - } + require.NoError(t, err) defer stateSqlDB.Close() //nolint:gosec,errcheck poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - t.Error(err) + log.Fatal(err) } - defer poolSqlDB.Close() //nolint:gosec,errcheck + eventLog := event.NewEventLog(event.Config{}, eventStorage) - st := newState(stateSqlDB) + st := newState(stateSqlDB, eventLog) genesisBlock := state.Block{ BlockNumber: 0, @@ -816,7 +844,7 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { initialBalance, _ := big.NewInt(0).SetString(encoding.MaxUint256StrNumber, encoding.Base10) initialBalance = initialBalance.Add(initialBalance, initialBalance) genesis := state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: operations.DefaultSequencerAddress, Type: int(merkletree.LeafTypeBalance), @@ -832,13 +860,11 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - t.Error(err) - } + require.NoError(t, err) type testCase struct { name string - createIncompatibleTx func() types.Transaction + createIncompatibleTx func() ethTypes.Transaction expectedError error } @@ -859,10 +885,10 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { testCases := []testCase{ { name: "Gas price over 256 bits", - createIncompatibleTx: func() types.Transaction { - tx := types.NewTransaction(uint64(0), + createIncompatibleTx: func() ethTypes.Transaction { + tx := ethTypes.NewTransaction(uint64(0), common.HexToAddress("0x1"), - big.NewInt(1), uint64(1), bigIntOver256Bits, nil) + big.NewInt(1), gasLimit, bigIntOver256Bits, nil) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) return *signedTx @@ -871,10 +897,10 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { }, { name: "Value over 256 bits", - createIncompatibleTx: func() types.Transaction { - tx := types.NewTransaction(uint64(0), + createIncompatibleTx: func() ethTypes.Transaction { + tx := ethTypes.NewTransaction(uint64(0), common.HexToAddress("0x1"), - bigIntOver256Bits, uint64(1), big.NewInt(1), nil) + bigIntOver256Bits, gasLimit, gasPrice, nil) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) return *signedTx @@ -883,11 +909,11 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { }, { name: "data over 30k bytes", - createIncompatibleTx: func() types.Transaction { + createIncompatibleTx: func() ethTypes.Transaction { data := [30001]byte{} - tx := types.NewTransaction(uint64(0), + tx := ethTypes.NewTransaction(uint64(0), common.HexToAddress("0x1"), - big.NewInt(1), uint64(1), big.NewInt(1), data[:]) + big.NewInt(1), 141004, gasPrice, data[:]) signedTx, err := auth.Signer(auth.From, tx) require.NoError(t, err) return *signedTx @@ -896,10 +922,10 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { }, { name: "chain id over 64 bits", - createIncompatibleTx: func() types.Transaction { - tx := types.NewTransaction(uint64(0), + createIncompatibleTx: func() ethTypes.Transaction { + tx := ethTypes.NewTransaction(uint64(0), common.HexToAddress("0x1"), - big.NewInt(1), uint64(1), big.NewInt(1), nil) + big.NewInt(1), gasLimit, gasPrice, nil) signedTx, err := authChainIdOver64Bits.Signer(authChainIdOver64Bits.From, tx) require.NoError(t, err) return *signedTx @@ -907,18 +933,17 @@ func Test_TryAddIncompatibleTxs(t *testing.T) { expectedError: fmt.Errorf("chain id higher than allowed, max allowed is %v", uint64(math.MaxUint64)), }, } - for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { incompatibleTx := testCase.createIncompatibleTx() - p := pool.NewPool(s, st, common.Address{}, incompatibleTx.ChainId().Uint64()) - err = p.AddTx(ctx, incompatibleTx) + p := setupPool(t, cfg, s, st, incompatibleTx.ChainId().Uint64(), ctx, eventLog) + err = p.AddTx(ctx, incompatibleTx, "") assert.Equal(t, testCase.expectedError, err) }) } } -func newState(sqlDB *pgxpool.Pool) *state.State { +func newState(sqlDB *pgxpool.Pool, eventLog *event.EventLog) *state.State { ctx := context.Background() stateDb := state.NewPostgresStorage(sqlDB) zkProverURI := testutils.GetEnv("ZKPROVER_URI", "localhost") @@ -928,15 +953,441 @@ func newState(sqlDB *pgxpool.Pool) *state.State { executorClient, _, _ := executor.NewExecutorClient(ctx, executorServerConfig) stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, mtDBServerConfig) stateTree := merkletree.NewStateTree(stateDBClient) - st := state.NewState(state.Config{MaxCumulativeGasUsed: 800000}, stateDb, executorClient, stateTree) + + st := state.NewState(state.Config{MaxCumulativeGasUsed: 800000, ChainID: chainID.Uint64(), ForkIDIntervals: []state.ForkIDInterval{{ + FromBatchNumber: 0, + ToBatchNumber: math.MaxUint64, + ForkId: 0, + Version: "", + }}}, stateDb, executorClient, stateTree, eventLog) return st } -func initOrResetDB() { - if err := dbutils.InitOrResetState(stateDBCfg); err != nil { - panic(err) +func initOrResetDB(t *testing.T) { + err := dbutils.InitOrResetState(stateDBCfg) + require.NoError(t, err) + + err = dbutils.InitOrResetPool(poolDBCfg) + require.NoError(t, err) +} + +func Test_AddTxWithIntrinsicGasTooLow(t *testing.T) { + initOrResetDB(t) + + stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + log.Fatal(err) } - if err := dbutils.InitOrResetPool(poolDBCfg); err != nil { - panic(err) + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + st := newState(stateSqlDB, eventLog) + + genesisBlock := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + ctx := context.Background() + dbTx, err := st.BeginStateTransaction(ctx) + require.NoError(t, err) + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) + + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) + require.NoError(t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + require.NoError(t, err) + + // insert transaction + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(0), + To: &common.Address{}, + Value: big.NewInt(0), + Gas: 0, + GasPrice: gasPrice, + Data: []byte{}, + }) + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.Error(t, err) + assert.Equal(t, err.Error(), pool.ErrIntrinsicGas.Error()) + + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(0), + To: nil, + Value: big.NewInt(10), + Gas: 0, + GasPrice: gasPrice, + Data: []byte{}, + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.Error(t, err) + assert.Equal(t, err.Error(), pool.ErrIntrinsicGas.Error()) + + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(0), + To: &common.Address{}, + Value: big.NewInt(10), + Gas: uint64(21000), + GasPrice: gasPrice, + Data: []byte{}, + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) + + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(1), + To: &common.Address{}, + Value: big.NewInt(10), + Gas: 0, + GasPrice: gasPrice, + Data: []byte("data inside tx"), + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.Error(t, err) + assert.Equal(t, err.Error(), pool.ErrIntrinsicGas.Error()) + + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(1), + To: &common.Address{}, + Value: big.NewInt(10), + Gas: uint64(21223), + GasPrice: gasPrice, + Data: []byte("data inside tx"), + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.Error(t, err) + assert.Equal(t, err.Error(), pool.ErrIntrinsicGas.Error()) + + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(1), + To: &common.Address{}, + Value: big.NewInt(10), + Gas: uint64(21224), + GasPrice: gasPrice, + Data: []byte("data inside tx"), + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) + + txs, err := p.GetPendingTxs(ctx, 0) + require.NoError(t, err) + assert.Equal(t, 2, len(txs)) + + for i := 0; i < 2; i++ { + assert.Equal(t, pool.TxStatusPending, txs[0].Status) + } +} + +func Test_AddTx_GasPriceErr(t *testing.T) { + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) + require.NoError(t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + require.NoError(t, err) + + auth.NoSend = true + auth.GasLimit = 53000 + auth.GasPrice = big.NewInt(0) + auth.Nonce = big.NewInt(0) + + require.NoError(t, err) + testCases := []struct { + name string + nonce uint64 + to *common.Address + gasLimit uint64 + gasPrice *big.Int + data []byte + expectedError error + }{ + { + name: "GasPriceTooLowErr", + nonce: 0, + to: nil, + gasLimit: gasLimit, + gasPrice: big.NewInt(0).SetUint64(gasPrice.Uint64() - uint64(1)), + data: []byte{}, + expectedError: pool.ErrGasPrice, + }, + } + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + log.Fatal(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + initOrResetDB(t) + + stateSqlDB, err := db.NewSQLDB(stateDBCfg) + if err != nil { + panic(err) + } + defer stateSqlDB.Close() //nolint:gosec,errcheck + + poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + st := newState(stateSqlDB, eventLog) + + genesisBlock := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: senderAddress, + Type: int(merkletree.LeafTypeBalance), + Value: "1000000000000000000000", + }, + }, + } + ctx := context.Background() + dbTx, err := st.BeginStateTransaction(ctx) + require.NoError(t, err) + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) + require.NoError(t, err) + + const chainID = 2576980377 + p := setupPool(t, cfg, s, st, chainID, ctx, eventLog) + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: tc.nonce, + To: tc.to, + Value: big.NewInt(0), + Gas: tc.gasLimit, + GasPrice: tc.gasPrice, + Data: tc.data, + }) + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) + require.NoError(t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) + require.NoError(t, err) + + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + + err = p.AddTx(ctx, *signedTx, "") + if tc.expectedError != nil { + require.ErrorIs(t, err, tc.expectedError) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_AddRevertedTx(t *testing.T) { + initOrResetDB(t) + + stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + log.Fatal(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + st := newState(stateSqlDB, eventLog) + + genesisBlock := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), } + ctx := context.Background() + dbTx, err := st.BeginStateTransaction(ctx) + require.NoError(t, err) + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) + + require.NoError(t, err) + p := setupPool(t, cfg, s, st, chainID.Uint64(), ctx, eventLog) + + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) + require.NoError(t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + require.NoError(t, err) + + // insert transaction + revertScData, err := hex.DecodeHex(Revert.RevertBin) + require.NoError(t, err) + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: uint64(0), + Gas: uint64(1000000), + GasPrice: gasPrice, + Data: revertScData, + }) + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) + + txs, err := p.GetPendingTxs(ctx, 0) + require.NoError(t, err) + assert.Equal(t, 1, len(txs)) + + for i := 0; i < 1; i++ { + assert.Equal(t, pool.TxStatusPending, txs[0].Status) + } +} + +func Test_BlockedAddress(t *testing.T) { + initOrResetDB(t) + + stateSqlDB, err := db.NewSQLDB(stateDBCfg) + require.NoError(t, err) + defer stateSqlDB.Close() //nolint:gosec,errcheck + + poolSqlDB, err := db.NewSQLDB(poolDBCfg) + require.NoError(t, err) + defer poolSqlDB.Close() //nolint:gosec,errcheck + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + log.Fatal(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + st := newState(stateSqlDB, eventLog) + + const chainID = 2576980377 + auth := operations.MustGetAuth(operations.DefaultSequencerPrivateKey, chainID) + + genesisBlock := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: auth.From.String(), + Type: int(merkletree.LeafTypeBalance), + Value: "1000000000000000000000", + }, + }, + } + ctx := context.Background() + dbTx, err := st.BeginStateTransaction(ctx) + require.NoError(t, err) + + _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) + + require.NoError(t, err) + + cfg := pool.Config{ + MaxTxBytesSize: 30132, + MaxTxDataBytesSize: 30000, + MinAllowedGasPriceInterval: cfgTypes.NewDuration(5 * time.Minute), + PollMinAllowedGasPriceInterval: cfgTypes.NewDuration(15 * time.Second), + DefaultMinGasPriceAllowed: 1000000000, + IntervalToRefreshBlockedAddresses: cfgTypes.NewDuration(5 * time.Second), + } + p := setupPool(t, cfg, s, st, chainID, ctx, eventLog) + + gasPrice, err := p.GetGasPrice(ctx) + require.NoError(t, err) + + // Add tx while address is not blocked + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: 0, + GasPrice: big.NewInt(0).SetInt64(int64(gasPrice)), + Gas: 24000, + To: &auth.From, + Value: big.NewInt(1000), + }) + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) + + // block address + _, err = poolSqlDB.Exec(ctx, "INSERT INTO pool.blocked(addr) VALUES($1)", auth.From.String()) + require.NoError(t, err) + + // wait it to refresh + time.Sleep(cfg.IntervalToRefreshBlockedAddresses.Duration) + + // get blocked when try to add new tx + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: 1, + GasPrice: big.NewInt(0).SetInt64(int64(gasPrice)), + Gas: 24000, + To: &auth.From, + Value: big.NewInt(1000), + }) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + + err = p.AddTx(ctx, *signedTx, "") + require.Equal(t, pool.ErrBlockedSender, err) + + // remove block + _, err = poolSqlDB.Exec(ctx, "DELETE FROM pool.blocked WHERE addr = $1", auth.From.String()) + require.NoError(t, err) + + // wait it to refresh + time.Sleep(cfg.IntervalToRefreshBlockedAddresses.Duration) + + // allowed to add tx again + err = p.AddTx(ctx, *signedTx, "") + require.NoError(t, err) +} + +func setupPool(t *testing.T, cfg pool.Config, s *pgpoolstorage.PostgresPoolStorage, st *state.State, chainID uint64, ctx context.Context, eventLog *event.EventLog) *pool.Pool { + p := pool.NewPool(cfg, s, st, l2BridgeAddr, chainID, eventLog) + + err := p.SetGasPrice(ctx, gasPrice.Uint64()) + require.NoError(t, err) + p.StartPollingMinSuggestedGasPrice(ctx) + return p } diff --git a/pool/transaction.go b/pool/transaction.go index 28a59c780d..24d5a81272 100644 --- a/pool/transaction.go +++ b/pool/transaction.go @@ -1,9 +1,9 @@ package pool import ( - "strings" "time" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) @@ -13,7 +13,7 @@ const ( TxStatusPending TxStatus = "pending" // TxStatusInvalid represents an invalid tx TxStatusInvalid TxStatus = "invalid" - // TxStatusSelected represents a tx that has been selected + // TxStatusSelected represents a tx that has been selected TxStatusSelected TxStatus = "selected" // TxStatusFailed represents a tx that has been failed after processing, but can be processed in the future TxStatusFailed TxStatus = "failed" @@ -27,60 +27,35 @@ func (s TxStatus) String() string { return string(s) } +// TxStatusUpdateInfo represents the information needed to update the status of a tx +type TxStatusUpdateInfo struct { + Hash common.Hash + NewStatus TxStatus + IsWIP bool + FailedReason *string +} + // Transaction represents a pool tx type Transaction struct { types.Transaction - Status TxStatus - IsClaims bool - ZkCounters - ReceivedAt time.Time + Status TxStatus + state.ZKCounters + ReceivedAt time.Time + PreprocessedStateRoot common.Hash + IsWIP bool + IP string + FailedReason *string } -// ZkCounters counters for the tx -type ZkCounters struct { - CumulativeGasUsed int64 - UsedKeccakHashes int32 - UsedPoseidonHashes int32 - UsedPoseidonPaddings int32 - UsedMemAligns int32 - UsedArithmetics int32 - UsedBinaries int32 - UsedSteps int32 -} - -// IsZkCountersBelowZero checks if any of the counters are below zero -func (zkc *ZkCounters) IsZkCountersBelowZero() bool { - return zkc.CumulativeGasUsed < 0 || - zkc.UsedArithmetics < 0 || - zkc.UsedSteps < 0 || - zkc.UsedBinaries < 0 || - zkc.UsedMemAligns < 0 || - zkc.UsedPoseidonPaddings < 0 || - zkc.UsedPoseidonHashes < 0 || - zkc.UsedKeccakHashes < 0 -} - -// SumUpZkCounters sum ups zk counters with passed tx zk counters -func (zkc *ZkCounters) SumUpZkCounters(txZkCounters ZkCounters) { - zkc.CumulativeGasUsed += txZkCounters.CumulativeGasUsed - zkc.UsedKeccakHashes += txZkCounters.UsedKeccakHashes - zkc.UsedPoseidonHashes += txZkCounters.UsedPoseidonHashes - zkc.UsedPoseidonPaddings += txZkCounters.UsedPoseidonPaddings - zkc.UsedMemAligns += txZkCounters.UsedMemAligns - zkc.UsedArithmetics += txZkCounters.UsedArithmetics - zkc.UsedBinaries += txZkCounters.UsedBinaries - zkc.UsedSteps += txZkCounters.UsedSteps -} - -// IsClaimTx checks, if tx is a claim tx -func (tx *Transaction) IsClaimTx(l2BridgeAddr common.Address) bool { - if tx.To() == nil { - return false +// NewTransaction creates a new transaction +func NewTransaction(tx types.Transaction, ip string, isWIP bool, p *Pool) *Transaction { + poolTx := Transaction{ + Transaction: tx, + Status: TxStatusPending, + ReceivedAt: time.Now(), + IsWIP: isWIP, + IP: ip, } - if *tx.To() == l2BridgeAddr && - strings.HasPrefix("0x"+common.Bytes2Hex(tx.Data()), bridgeClaimMethodSignature) { - return true - } - return false + return &poolTx } diff --git a/pool/transaction_test.go b/pool/transaction_test.go deleted file mode 100644 index d7b3067e20..0000000000 --- a/pool/transaction_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package pool - -import ( - "math/big" - "testing" - - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -func Test_IsClaimTx(t *testing.T) { - l2BridgeAddr := common.HexToAddress("0x00000000000000000000000000000001") - differentAddr := common.HexToAddress("0x00000000000000000000000000000002") - claimData := hex.DecodeHexToBig(bridgeClaimMethodSignature).Bytes() - - testCases := []struct { - Name string - Tx Transaction - expectedResult bool - }{ - { - Name: "To address as nil", - Tx: Transaction{ - Transaction: *types.NewTx(&types.LegacyTx{Nonce: 1, To: nil, Value: big.NewInt(0), Gas: 0, GasPrice: big.NewInt(0), Data: claimData}), - }, - expectedResult: false, - }, - { - Name: "To address as Zeroaddress", - Tx: Transaction{ - Transaction: *types.NewTx(&types.LegacyTx{Nonce: 1, To: &common.Address{}, Value: big.NewInt(0), Gas: 0, GasPrice: big.NewInt(0), Data: claimData}), - }, - expectedResult: false, - }, - { - Name: "To address as Any address other than l2BridgeAddr address", - Tx: Transaction{ - Transaction: *types.NewTx(&types.LegacyTx{Nonce: 1, To: &differentAddr, Value: big.NewInt(0), Gas: 0, GasPrice: big.NewInt(0), Data: claimData}), - }, - expectedResult: false, - }, - { - Name: "To address as l2BridgeAddr address", - Tx: Transaction{ - Transaction: *types.NewTx(&types.LegacyTx{Nonce: 1, To: &l2BridgeAddr, Value: big.NewInt(0), Gas: 0, GasPrice: big.NewInt(0), Data: claimData}), - }, - expectedResult: false, - }, - { - Name: "To address as l2BridgeAddr address", - Tx: Transaction{ - Transaction: *types.NewTx(&types.LegacyTx{Nonce: 1, To: &l2BridgeAddr, Value: big.NewInt(0), Gas: 0, GasPrice: big.NewInt(0), Data: claimData}), - }, - expectedResult: false, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.Name, func(t *testing.T) { - result := testCase.Tx.IsClaimTx(l2BridgeAddr) - if result != testCase.expectedResult { - t.Errorf("Invalid result, expected: %v, found: %v", testCase.expectedResult, result) - } - }) - } -} diff --git a/proto/src/proto/aggregator/v1/aggregator.proto b/proto/src/proto/aggregator/v1/aggregator.proto new file mode 100644 index 0000000000..66be538775 --- /dev/null +++ b/proto/src/proto/aggregator/v1/aggregator.proto @@ -0,0 +1,296 @@ +syntax = "proto3"; + +package aggregator.v1; + +option go_package = "github.com/0xPolygonHermez/zkevm-node/aggregator/pb"; + +message Version { + string v0_0_1 = 1; +} + +// timestamps are represented in unix time in seconds + +/** + * Define all methods implementes by the gRPC + * Channel: prover receives aggregator messages and returns prover messages with the same id + */ +service AggregatorService { + rpc Channel(stream ProverMessage) returns (stream AggregatorMessage) {} +} + +message AggregatorMessage +{ + string id = 1; + oneof request + { + GetStatusRequest get_status_request = 2; + GenBatchProofRequest gen_batch_proof_request = 3; + GenAggregatedProofRequest gen_aggregated_proof_request = 4; + GenFinalProofRequest gen_final_proof_request = 5; + CancelRequest cancel_request = 6; + GetProofRequest get_proof_request = 7; + } +} + +message ProverMessage +{ + string id = 1; + oneof response + { + GetStatusResponse get_status_response = 2; + GenBatchProofResponse gen_batch_proof_response = 3; + GenAggregatedProofResponse gen_aggregated_proof_response = 4; + GenFinalProofResponse gen_final_proof_response = 5; + CancelResponse cancel_response = 6; + GetProofResponse get_proof_response = 7; + } +} + +/////////////////// +// Request messages +/////////////////// + +/** + * @dev GetStatusRequest + */ +message GetStatusRequest {} + +/** + * @dev GenBatchProofRequest + * @param {input} - input prover + */ +message GenBatchProofRequest { + InputProver input = 1; +} + +/** + * @dev GenAggregatedProofRequest + * @param {recursive_proof_1} - proof json of the first batch to aggregate + * @param {recursive_proof_2} - proof json of the second batch to aggregate + */ +message GenAggregatedProofRequest { + string recursive_proof_1 = 1; + string recursive_proof_2 = 2; +} + +/** + * @dev GenFinalProofRequest + * @param {recursive_proof} - proof json of the batch or aggregated proof to finalise + * @param {aggregator_addr} - address of the aggregator + */ +message GenFinalProofRequest { + string recursive_proof = 1; + string aggregator_addr = 2; +} + +/** + * @dev CancelRequest + * @param {id} - identifier of the proof request to cancel + */ + message CancelRequest { + string id = 1; +} + +/** + * @dev Request GetProof + * @param {id} - proof identifier of the proof request + * @param {timeout} - time to wait until the service responds + */ +message GetProofRequest { + string id = 1; + uint64 timeout = 2; +} + +///////////////////// +// Responses messages +///////////////////// + +/** + * @dev Response GetStatus + * @param {status} - server status + * - BOOTING: being ready to compute proofs + * - COMPUTING: busy computing a proof + * - IDLE: waiting for a proof to compute + * - HALT: stop + * @param {last_computed_request_id} - last proof identifier that has been computed + * @param {last_computed_end_time} - last proof timestamp when it was finished + * @param {current_computing_request_id} - id of the proof that is being computed + * @param {current_computing_start_time} - timestamp when the proof that is being computed started + * @param {version_proto} - .proto verion + * @param {version_server} - server version + * @param {pending_request_queue_ids} - list of identifierss of proof requests that are in the pending queue + * @param {prover_name} - id of this prover server, normally specified via config.json, or UNSPECIFIED otherwise; it does not change if prover reboots + * @param {prover_id} - id of this prover instance or reboot; it changes if prover reboots; it is a UUID, automatically generated during the initialization + * @param {number_of_cores} - number of cores in the system where the prover is running + * @param {total_memory} - total memory in the system where the prover is running + * @param {free_memory} - free memory in the system where the prover is running + */ +message GetStatusResponse { + enum Status { + STATUS_UNSPECIFIED = 0; + STATUS_BOOTING = 1; + STATUS_COMPUTING = 2; + STATUS_IDLE = 3; + STATUS_HALT = 4; + } + Status status = 1; + string last_computed_request_id = 2; + uint64 last_computed_end_time = 3; + string current_computing_request_id = 4; + uint64 current_computing_start_time = 5; + string version_proto = 6; + string version_server = 7; + repeated string pending_request_queue_ids = 8; + string prover_name = 9; + string prover_id = 10; + uint64 number_of_cores = 11; + uint64 total_memory = 12; + uint64 free_memory = 13; + uint64 fork_id = 14; +} + +/** + * @dev Result + * - OK: succesfully completed + * - ERROR: request is not correct, i.e. input data is wrong + * - INTERNAL_ERROR: internal server error when delivering the response + */ +enum Result { + RESULT_UNSPECIFIED = 0; + RESULT_OK = 1; + RESULT_ERROR = 2; + RESULT_INTERNAL_ERROR = 3; +} + +/** + * @dev GenBatchProofResponse + * @param {id} - proof identifier, to be used in GetProofRequest() + * @param {result} - request result + */ +message GenBatchProofResponse { + string id = 1; + Result result = 2; +} + +/** + * @dev GenAggregatedProofResponse + * @param {id} - proof identifier, to be used in GetProofRequest() + * @param {result} - request result + */ +message GenAggregatedProofResponse { + string id = 1; + Result result = 2; +} + +/** + * @dev Response GenFinalProof + * @param {id} - proof identifier, to be used in GetProofRequest() + * @param {result} - request result + */ +message GenFinalProofResponse { + string id = 1; + Result result = 2; +} + +/** + * @dev CancelResponse + * @param {result} - request result + */ +message CancelResponse { + Result result = 1; +} + +/** + * @dev GetProofResponse + * @param {id} - proof identifier + * @param {final_proof} - groth16 proof + public circuit inputs + * @param {recursive_proof} - recursive proof json + * @param {result} - proof result + * - COMPLETED_OK: proof has been computed successfully and it is valid + * - ERROR: request error + * - COMPLETED_ERROR: proof has been computed successfully and it is not valid + * - PENDING: proof is being computed + * - INTERNAL_ERROR: server error during proof computation + * - CANCEL: proof has been cancelled + * @param {result_string} - extends result information + */ +message GetProofResponse { + enum Result { + RESULT_UNSPECIFIED = 0; + RESULT_COMPLETED_OK = 1; + RESULT_ERROR = 2; + RESULT_COMPLETED_ERROR = 3; + RESULT_PENDING = 4; + RESULT_INTERNAL_ERROR = 5; + RESULT_CANCEL = 6; + } + string id = 1; + oneof proof { + FinalProof final_proof = 2; + string recursive_proof =3; + } + Result result = 4; + string result_string = 5; +} + +/* + * @dev FinalProof + * @param {proof} - groth16 proof + * @param {public} - public circuit inputs +*/ +message FinalProof { + string proof = 1; + PublicInputsExtended public = 2; +} + +/* + * @dev PublicInputs + * @param {old_state_root} + * @param {old_acc_input_hash} + * @param {old_batch_num} + * @param {chain_id} + * @param {batch_l2_data} + * @param {global_exit_root} + * @param {sequencer_addr} + * @param {aggregator_addr} + */ +message PublicInputs { + bytes old_state_root = 1; + bytes old_acc_input_hash = 2; + uint64 old_batch_num = 3; + uint64 chain_id = 4; + uint64 fork_id = 5; + bytes batch_l2_data = 6; + bytes global_exit_root = 7; + uint64 eth_timestamp = 8; + string sequencer_addr = 9; + string aggregator_addr = 10; +} + +/** + * @dev InputProver + * @param {public_inputs} - public inputs + * @param {db} - database containing all key-values in smt matching the old state root + * @param {contracts_bytecode} - key is the hash(contractBytecode), value is the bytecode itself + */ +message InputProver { + PublicInputs public_inputs = 1; + map db = 4; // For debug/testing purpposes only. Don't fill this on production + map contracts_bytecode = 5; // For debug/testing purpposes only. Don't fill this on production +} + +/** + * @dev PublicInputsExtended + * @param {public_inputs} - public inputs + * @param {new_state_root} - final state root. Used as a sanity check. + * @param {new_acc_input_hash} - final accumulate input hash. Used as a sanity check. + * @param {new_local_exit_root} - new local exit root. Used as a sanity check. + * @param {new_batch_num} - final num batch. Used as a sanity check. + */ +message PublicInputsExtended { + PublicInputs public_inputs = 1; + bytes new_state_root = 2; + bytes new_acc_input_hash = 3; + bytes new_local_exit_root = 4; + uint64 new_batch_num = 5; +} diff --git a/proto/src/proto/broadcast/v1/broadcast.proto b/proto/src/proto/broadcast/v1/broadcast.proto deleted file mode 100644 index 5879506600..0000000000 --- a/proto/src/proto/broadcast/v1/broadcast.proto +++ /dev/null @@ -1,40 +0,0 @@ -/** -* Broadcast service. -**/ - -syntax = "proto3"; - -import "google/protobuf/empty.proto"; - -package broadcast.v1; - -option go_package = "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb"; - -service BroadcastService { - rpc GetLastBatch(google.protobuf.Empty) returns (GetBatchResponse); - rpc GetBatch(GetBatchRequest) returns (GetBatchResponse); -} - -// Requests -message GetBatchRequest { - uint64 batch_number = 1; -} - -// Responses -message GetBatchResponse { - uint64 batch_number = 1; - string global_exit_root = 2; - string local_exit_root = 3; - string state_root = 4; - string mainnet_exit_root = 5; - string rollup_exit_root = 6; - uint64 timestamp = 7; - string sequencer = 8; - uint64 forced_batch_number = 9; - repeated Transaction transactions = 10; -} - -// Common -message Transaction { - string encoded = 1; -} diff --git a/proto/src/proto/executor/v1/executor.proto b/proto/src/proto/executor/v1/executor.proto index 88665af82f..d377578cb8 100644 --- a/proto/src/proto/executor/v1/executor.proto +++ b/proto/src/proto/executor/v1/executor.proto @@ -10,30 +10,31 @@ service ExecutorService { } message ProcessBatchRequest { - uint64 batch_num = 1; - string coinbase = 2; - bytes batch_l2_data = 3; - // from is used for unsigned transactions with sender - string from = 4; - bytes old_state_root = 5; - bytes global_exit_root = 6; - bytes old_local_exit_root = 7; + bytes old_state_root = 1; + bytes old_acc_input_hash = 2; + uint64 old_batch_num = 3; + uint64 chain_id = 4; + uint64 fork_id = 5; + bytes batch_l2_data = 6; + bytes global_exit_root = 7; uint64 eth_timestamp = 8; - uint32 update_merkle_tree = 9; - bytes tx_hash_to_generate_execute_trace = 10; - bytes tx_hash_to_generate_call_trace = 11; + string coinbase = 9; + uint32 update_merkle_tree = 10; + // flag to indicate that counters should not be taken into account + uint64 no_counters = 11; + // from is used for unsigned transactions with sender + string from = 12; // For testing purposes only - map db = 12; - map contracts_bytecode = 13; // For debug/testing purpposes only. Don't fill this on production - uint64 chain_id = 14; - uint64 no_counters = 15; + map db = 13; + map contracts_bytecode = 14; // For debug/testing purpposes only. Don't fill this on production + TraceConfig trace_config = 15; } message ProcessBatchResponse { - uint64 cumulative_gas_used = 1; - repeated ProcessTransactionResponse responses = 2; - bytes new_state_root = 3; - bytes new_local_exit_root = 4; + bytes new_state_root = 1; + bytes new_acc_input_hash = 2; + bytes new_local_exit_root = 3; + uint64 new_batch_num = 4; uint32 cnt_keccak_hashes = 5; uint32 cnt_poseidon_hashes = 6; uint32 cnt_poseidon_paddings = 7; @@ -41,7 +42,32 @@ message ProcessBatchResponse { uint32 cnt_arithmetics = 9; uint32 cnt_binaries = 10; uint32 cnt_steps = 11; - Error error = 12; + uint64 cumulative_gas_used = 12; + repeated ProcessTransactionResponse responses = 13; + ExecutorError error = 14; + map read_write_addresses = 15; +} + +// Trace configuration request params +message TraceConfig { + // Disables storage (default=false) + uint32 disable_storage = 1; + // Disables stack (default=false) + uint32 disable_stack = 2; + // Enables memory (default=false) + uint32 enable_memory = 3; + // Enables return data (default=false) + uint32 enable_return_data = 4; + // Hash of tx in batch to retrieve the execution trace + bytes tx_hash_to_generate_execute_trace = 5; + // Hash of tx in batch to retrieve the call trace + bytes tx_hash_to_generate_call_trace = 6; +} +message InfoReadWrite { + // If nonce="" then it has not been set; if set, string is in decimal (base 10) + string nonce = 1; + // If balance="" then it has not been set; if set, string is in decimal (base 10) + string balance = 2; } message CallTrace { @@ -99,7 +125,7 @@ message TransactionStep { // Contract information Contract contract = 11; // Error - Error error = 12; + RomError error = 12; } message Contract { @@ -128,7 +154,7 @@ message ProcessTransactionResponse { // Total gas refunded as result of execution uint64 gas_refunded = 7; // Any error encountered during the execution - Error error = 8; + RomError error = 8; // New SC Address in case of SC creation string create_address = 9; // State Root @@ -183,42 +209,91 @@ message ExecutionTraceStep { // Gas refund uint64 gas_refund = 11; // Error - Error error = 12; + RomError error = 12; +} + +enum RomError { + ROM_ERROR_UNSPECIFIED = 0; + // ROM_ERROR_NO_ERROR indicates the execution ended successfully + ROM_ERROR_NO_ERROR = 1; + // ROM_ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution + ROM_ERROR_OUT_OF_GAS = 2; + // ROM_ERROR_STACK_OVERFLOW indicates a stack overflow has happened + ROM_ERROR_STACK_OVERFLOW = 3; + // ROM_ERROR_STACK_UNDERFLOW indicates a stack overflow has happened + ROM_ERROR_STACK_UNDERFLOW = 4; + // ROM_ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum + ROM_ERROR_MAX_CODE_SIZE_EXCEEDED = 5; + // ROM_ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses + ROM_ERROR_CONTRACT_ADDRESS_COLLISION = 6; + // ROM_ERROR_EXECUTION_REVERTED indicates the execution has been reverted + ROM_ERROR_EXECUTION_REVERTED = 7; + // ROM_ERROR_OUT_OF_COUNTERS_STEP indicates there is not enough step counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_STEP = 8; + // ROM_ERROR_OUT_OF_COUNTERS_KECCAK indicates there is not enough keccak counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_KECCAK = 9; + // ROM_ERROR_OUT_OF_COUNTERS_BINARY indicates there is not enough binary counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_BINARY = 10; + // ROM_ERROR_OUT_OF_COUNTERS_MEM indicates there is not enough memory aligncounters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_MEM = 11; + // ROM_ERROR_OUT_OF_COUNTERS_ARITH indicates there is not enough arith counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_ARITH = 12; + // ROM_ERROR_OUT_OF_COUNTERS_PADDING indicates there is not enough padding counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_PADDING = 13; + // ROM_ERROR_OUT_OF_COUNTERS_POSEIDON indicates there is not enough poseidon counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_POSEIDON = 14; + // ROM_ERROR_INVALID_JUMP indicates there is an invalid jump opcode + ROM_ERROR_INVALID_JUMP = 15; + // ROM_ERROR_INVALID_OPCODE indicates there is an invalid opcode + ROM_ERROR_INVALID_OPCODE = 16; + // ROM_ERROR_INVALID_STATIC indicates there is an invalid static call + ROM_ERROR_INVALID_STATIC = 17; + // ROM_ERROR_INVALID_BYTECODE_STARTS_EF indicates there is a bytecode starting with 0xEF + ROM_ERROR_INVALID_BYTECODE_STARTS_EF = 18; + // ROM_ERROR_INTRINSIC_INVALID_SIGNATURE indicates the transaction is failing at the signature intrinsic check + ROM_ERROR_INTRINSIC_INVALID_SIGNATURE = 19; + // ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID indicates the transaction is failing at the chain id intrinsic check + ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID = 20; + // ROM_ERROR_INTRINSIC_INVALID_NONCE indicates the transaction is failing at the nonce intrinsic check + ROM_ERROR_INTRINSIC_INVALID_NONCE = 21; + // ROM_ERROR_INTRINSIC_INVALID_GAS indicates the transaction is failing at the gas limit intrinsic check + ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT = 22; + // ROM_ERROR_INTRINSIC_INVALID_BALANCE indicates the transaction is failing at balance intrinsic check + ROM_ERROR_INTRINSIC_INVALID_BALANCE = 23; + // ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT indicates the batch is exceeding the batch gas limit + ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT = 24; + // ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE indicates the transaction sender is invalid + ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE = 25; + // ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW indicates the transaction gasLimit*gasPrice > MAX_UINT_256 - 1 + ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW = 26; + // ROM_ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed + ROM_ERROR_BATCH_DATA_TOO_BIG = 27; + // ROM_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + ROM_ERROR_UNSUPPORTED_FORK_ID = 28; } -enum Error { - ERROR_UNSPECIFIED = 0; - // ERROR_NO_ERROR indicates the execution ended successfully - ERROR_NO_ERROR = 1; - // ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution - ERROR_OUT_OF_GAS = 2; - // ERROR_STACK_OVERFLOW indicates a stack overflow has happened - ERROR_STACK_OVERFLOW = 3; - // ERROR_STACK_UNDERFLOW indicates a stack overflow has happened - ERROR_STACK_UNDERFLOW = 4; - // ERROR_NOT_ENOUGH_FUNDS indicates there is not enough funds to continue the execution - ERROR_NOT_ENOUGH_FUNDS = 5; - // ERROR_INSUFFICIENT_BALANCE indicates there is not enough balance to continue the execution - ERROR_INSUFFICIENT_BALANCE = 6; - // ERROR_CODE_NOT_FOUND indicates the code was not found - ERROR_CODE_NOT_FOUND = 7; - // ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum - ERROR_MAX_CODE_SIZE_EXCEEDED = 8; - // ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses - ERROR_CONTRACT_ADDRESS_COLLISION = 9; - // ERROR_DEPTH indicates the maximun call depth has been passed - ERROR_DEPTH= 10; - // ERROR_EXECUTION_REVERTED indicates the execution has been reverted - ERROR_EXECUTION_REVERTED = 11; - // ERROR_CODE_STORE_OUT_OF_GAS indicates there is not enough gas for the storage - ERROR_CODE_STORE_OUT_OF_GAS = 12; - // ERROR_OUT_OF_COUNTERS indicates there is not enough counters to continue the execution - ERROR_OUT_OF_COUNTERS = 13; - // ERROR_INVALID_TX indicates the transaction is invalid because of invalid jump dest, invalid opcode, invalid deploy - // or invalid static tx - ERROR_INVALID_TX = 14; - // ERROR_INTRINSIC_INVALID_TX indicates the transaction is failing at the intrinsic checks - ERROR_INTRINSIC_INVALID_TX = 15; - // ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed - ERROR_BATCH_DATA_TOO_BIG = 16; +enum ExecutorError { + EXECUTOR_ERROR_UNSPECIFIED = 0; + // EXECUTOR_ERROR_NO_ERROR indicates there was no error + EXECUTOR_ERROR_NO_ERROR = 1; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK indicates that the keccak counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK = 2; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY indicates that the binary counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY = 3; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM indicates that the memory align counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM = 4; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH indicates that the arith counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH = 5; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING indicates that the padding counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING = 6; + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON indicates that the poseidon counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON = 7; + // EXECUTOR_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + EXECUTOR_ERROR_UNSUPPORTED_FORK_ID = 8; + // EXECUTOR_ERROR_BALANCE_MISMATCH indicates that there is a balance mismatch error in the ROM + EXECUTOR_ERROR_BALANCE_MISMATCH = 9; + // EXECUTOR_ERROR_FEA2SCALAR indicates that there is a fea2scalar error in the execution + EXECUTOR_ERROR_FEA2SCALAR = 10; + // EXECUTOR_ERROR_TOS32 indicates that there is a TOS32 error in the execution + EXECUTOR_ERROR_TOS32 = 11; } diff --git a/proto/src/proto/statedb/v1/statedb.proto b/proto/src/proto/statedb/v1/statedb.proto index 7a223f12fb..25476dfeac 100644 --- a/proto/src/proto/statedb/v1/statedb.proto +++ b/proto/src/proto/statedb/v1/statedb.proto @@ -16,8 +16,8 @@ message Version { * Define all methods implementes by the gRPC * Get: get the value for a specific key * Set: set the value for a specific key - * SetProgram: set the byte data for a specific hash - * GetProgram: get the byte data for a specific hash + * SetProgram: set the byte data for a specific key + * GetProgram: get the byte data for a specific key * Flush: wait for all the pendings writes to the DB are done */ service StateDBService { @@ -25,7 +25,9 @@ service StateDBService { rpc Get(GetRequest) returns (GetResponse) {} rpc SetProgram(SetProgramRequest) returns (SetProgramResponse) {} rpc GetProgram(GetProgramRequest) returns (GetProgramResponse) {} - rpc Flush (google.protobuf.Empty) returns (google.protobuf.Empty) {} + rpc LoadDB(LoadDBRequest) returns (google.protobuf.Empty) {} + rpc LoadProgramDB(LoadProgramDBRequest) returns (google.protobuf.Empty) {} + rpc Flush (google.protobuf.Empty) returns (FlushResponse) {} } /////////////////// @@ -37,8 +39,9 @@ service StateDBService { * @param {old_root} - merkle-tree root * @param {key} - key to set * @param {value} - scalar value to set (HEX string format) - * @param {persistent} - indicates if it should be stored in the database (true) or only in the memory cache (false) + * @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) * @param {details} - indicates if it should return all response parameters (true) or just the new root (false) + * @param {get_db_read_log} - indicates if it should return the DB reads generated during the execution of the request */ message SetRequest { Fea old_root = 1; @@ -46,6 +49,7 @@ message SetRequest { string value = 3; bool persistent = 4; bool details = 5; + bool get_db_read_log = 6; } /** @@ -53,18 +57,20 @@ message SetRequest { * @param {root} - merkle-tree root * @param {key} - key to look for * @param {details} - indicates if it should return all response parameters (true) or just the new root (false) + * @param {get_db_read_log} - indicates if it should return the DB reads generated during the execution of the request */ message GetRequest { Fea root = 1; Fea key = 2; bool details = 3; + bool get_db_read_log = 4; } /** * @dev SetProgramRequest - * @param {key} - hash to set + * @param {key} - key to set * @param {data} - Program data to store - * @param {persistent} - indicates if it should be stored in the database (true) or only in the memory cache (false) + * @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) */ message SetProgramRequest { Fea key = 1; @@ -74,12 +80,32 @@ message SetProgramRequest { /** * @dev GetProgramRequest - * @param {key} - hash to get program data + * @param {key} - key to get program data */ message GetProgramRequest { Fea key = 1; } +/** + * @dev LoadDBRequest + * @param {input_db} - list of db records (MT) to load in the database + * @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) + */ +message LoadDBRequest { + map input_db = 1; + bool persistent = 2; +} + +/** + * @dev LoadProgramDBRequest + * @param {input_program_db} - list of db records (program) to load in the database + * @param {persistent} - indicates if it should be stored in the SQL database (true) or only in the memory cache (false) + */ +message LoadProgramDBRequest { + map input_program_db = 1; + bool persistent = 2; +} + ///////////////////// // Responses messages ///////////////////// @@ -96,6 +122,8 @@ message GetProgramRequest { * @param {old_value} - old value (HEX string format) * @param {new_value} - new value (HEX string format) * @param {mode} + * @param {proof_hash_counter} + * @param {db_read_log} - list of db records read during the execution of the request * @param {result} - result code */ message SetResponse { @@ -109,7 +137,9 @@ message SetResponse { string old_value = 8; string new_value = 9; string mode = 10; - ResultCode result = 11; + uint64 proof_hash_counter = 11; + map db_read_log = 12; + ResultCode result = 13; } /** @@ -121,6 +151,8 @@ message SetResponse { * @param {ins_value} - value found (HEX string format) * @param {is_old0} - is new insert or delete * @param {value} - value retrieved (HEX string format) + * @param {proof_hash_counter} + * @param {db_read_log} - list of db records read during the execution of the request * @param {result} - result code */ message GetResponse { @@ -131,7 +163,9 @@ message GetResponse { string ins_value = 5; bool is_old0 = 6; string value = 7; - ResultCode result = 8; + uint64 proof_hash_counter = 8; + map db_read_log = 9; + ResultCode result = 10; } /** @@ -152,6 +186,14 @@ message GetProgramResponse { ResultCode result = 2; } +/** + * @dev FlushResponse + * @param {result} - result code + */ +message FlushResponse { + ResultCode result = 1; +} + /** * @dev Array of 4 FE * @param {fe0} - Field Element value for pos 0 @@ -166,9 +208,17 @@ message Fea { uint64 fe3 = 4; } +/** + * @dev FE (Field Element) List + * @param {fe} - list of Fe +*/ +message FeList { + repeated uint64 fe = 1; +} + /** * @dev Siblings List - * @param {sibling} - sibling + * @param {sibling} - list of siblings */ message SiblingList { repeated uint64 sibling = 1; @@ -182,9 +232,10 @@ message ResultCode { enum Code { CODE_UNSPECIFIED = 0; CODE_SUCCESS = 1; - CODE_KEY_NOT_FOUND = 2; - CODE_DB_ERROR = 3; + CODE_DB_KEY_NOT_FOUND = 2; // Requested key was not found in database + CODE_DB_ERROR = 3; // Error connecting to database, or processing request CODE_INTERNAL_ERROR = 4; + CODE_SMT_INVALID_DATA_SIZE = 14; // Invalid size for the data of MT node } Code code = 1; } diff --git a/proto/src/proto/zkprover/v1/zk_prover.proto b/proto/src/proto/zkprover/v1/zk_prover.proto deleted file mode 100644 index 328d5e06e6..0000000000 --- a/proto/src/proto/zkprover/v1/zk_prover.proto +++ /dev/null @@ -1,233 +0,0 @@ -syntax = "proto3"; - -package zkprover.v1; - -option go_package = "github.com/0xPolygonHermez/zkevm-node/proverclient/pb"; - -message Version { - string v0_0_1 = 1; -} - -// timestamps are represented in unix time in seconds - -/** - * Define all methods implementes by the gRPC - * GetStatus: get server report about its current state (non-blocking call) - * GenProof: ask prover to start proof generation. If prover is biusy, request is queued (non-blocking call) - * Cancel: ask prover to cancel specific proof (non-blocking call) - * GetProof: retrieve proof information given a timeout (blocking call) - */ -service ZKProverService { - rpc GetStatus(GetStatusRequest) returns (GetStatusResponse) {} - rpc GenProof(GenProofRequest) returns (GenProofResponse) {} - rpc Cancel(CancelRequest) returns (CancelResponse) {} - rpc GetProof(stream GetProofRequest) returns (stream GetProofResponse) {} -} - -/////////////////// -// Request messages -/////////////////// - -/** - * @dev GetStatusRequest - */ -message GetStatusRequest {} - -/** - * @dev GenProofRequest - * @param {input} - input prover - */ -message GenProofRequest { - InputProver input = 1; -} - -/** - * @dev CancelRequest - * @param {id} - proof identifier - */ - message CancelRequest { - string id = 1; -} - -/** - * @dev Request GetProof - * @param {id} - proof identifier - * @param {timeout} - time to wait until the service responds - */ -message GetProofRequest { - string id = 1; - uint64 timeout = 2; -} - -///////////////////// -// Responses messages -///////////////////// - -/** - * @dev Response GetStatus - * @param {state} - server state - * - BOOTING: being ready to compute proofs - * - COMPUTING: busy computing a proof - * - IDLE: waiting for a proof to compute - * - HALT: stop - * @param {last_computed_request_id} - last proof identifier that has been computed - * @param {last_computed_end_time} - last proof timestamp when it was finished - * @param {current_computing_request_id} - current proof identifier that ius being computed - * @param {current_computing_start_time} - current proof timestamp when it was started - * @param {version_proto} - .proto verion - * @param {version_server} - server version - * @param {pending_request_queue_ids} - list of pending proof identifier that are in the queue - */ -message GetStatusResponse { - enum StatusProver { - STATUS_PROVER_UNSPECIFIED = 0; - STATUS_PROVER_BOOTING = 1; - STATUS_PROVER_COMPUTING = 2; - STATUS_PROVER_IDLE = 3; - STATUS_PROVER_HALT = 4; - } - StatusProver state = 1; - string last_computed_request_id = 2; - uint64 last_computed_end_time = 3; - string current_computing_request_id = 4; - uint64 current_computing_start_time = 5; - string version_proto = 6; - string version_server = 7; - repeated string pending_request_queue_ids = 8; -} - -/** - * @dev Response GenProof - * @param {id} - proof identifier - * @param {result} - response result - * - OK: succesfull response - * - ERROR: request is not correct - * - INTERNAL_ERROR: server error when delivering the response - */ -message GenProofResponse { - enum ResultGenProof { - RESULT_GEN_PROOF_UNSPECIFIED = 0; - RESULT_GEN_PROOF_OK = 1; - RESULT_GEN_PROOF_ERROR = 2; - RESULT_GEN_PROOF_INTERNAL_ERROR = 3; - } - string id = 1; - ResultGenProof result = 2; -} - -/** - * @dev CancelResponse - * @param {result} - request result - * - OK: proof has been cancelled - * - ERROR: proof has not been cancelled - */ -message CancelResponse { - enum ResultCancel { - RESULT_CANCEL_UNSPECIFIED = 0; - RESULT_CANCEL_OK = 1; - RESULT_CANCEL_ERROR = 2; - } - ResultCancel result = 1; -} - -/** - * @dev GetProofResponse - * @param {id} - proof identifier - * @param {proof} - groth16 proof - * @param {public} - public circuit inputs - * @param {result} - response result - * - COMPLETED_OK: proof has been computed successfully and it is valid - * - ERROR: request error - * - COMPLETED_ERROR: proof has been computed successfully and it is not valid - * - PENDING: proof is being computed - * - INTERNAL_ERROR: server error during proof computation - * - CANCEL: proof has been cancelled - * @param {result_string} - extends result information - */ -message GetProofResponse { - enum ResultGetProof { - RESULT_GET_PROOF_UNSPECIFIED = 0; - RESULT_GET_PROOF_COMPLETED_OK = 1; - RESULT_GET_PROOF_ERROR = 2; - RESULT_GET_PROOF_COMPLETED_ERROR = 3; - RESULT_GET_PROOF_PENDING = 4; - RESULT_GET_PROOF_INTERNAL_ERROR = 5; - RESULT_GET_PROOF_CANCEL = 6; - } - string id = 1; - Proof proof = 2; - PublicInputsExtended public = 3; - ResultGetProof result = 4; - string result_string = 5; -} - -/* - * @dev PublicInputs - * @param {old_state_root} - * @param {old_local_exit_root} - * @param {new_state_root} - * @param {new_local_exit_root} - * @param {sequencer_addr} - * @param {batch_hash_data} - * @param {batch_num} - * @param {eth_timestamp} - */ -message PublicInputs { - string old_state_root = 1; - string old_local_exit_root = 2; - string new_state_root = 3; - string new_local_exit_root = 4; - string sequencer_addr = 5; - string batch_hash_data = 6; - uint32 batch_num = 7; - uint64 eth_timestamp = 8; - string aggregator_addr = 9; - uint64 chain_id = 10; -} - -/** - * @dev ProofB - * @param {proofs} - two elliptic curves points - */ -message ProofB { - repeated string proofs = 1; -} - -/** - * @dev Proof - * @param {proof_a} - elliptic curve point - * @param {proof_b} - two elliptic curves points - * @param {proof_c} - elliptic curve point - */ -message Proof { - repeated string proof_a = 1; - repeated ProofB proof_b = 2; - repeated string proof_c = 3; -} - -/** - * @dev InputProver - * @param {public_inputs} - public inputs - * @param {global_exit_root} - bridge global exit root - * @param {batch_l2_data} - contract calldata - * @param {address_aggregator} - ethereum address aggregator - * @param {db} - database containing all key-values in smt matching the old state root - * @param {contracts_bytecode} - key is the hash(contractBytecode), value is the bytecode itself - */ -message InputProver { - PublicInputs public_inputs = 1; - string global_exit_root = 2; - string batch_l2_data = 3; - map db = 4; // For debug/testing purpposes only. Don't fill this on production - map contracts_bytecode = 5; // For debug/testing purpposes only. Don't fill this on production -} - -/** - * @dev PublicInputsExtended - * @param {public_inputs} - public inputs - * @param {input_hash} - global hash of all public inputs. Used as a sanity check. - */ -message PublicInputsExtended { - PublicInputs public_inputs = 1; - string input_hash = 2; -} diff --git a/proverclient/config.go b/proverclient/config.go deleted file mode 100644 index e5160561f4..0000000000 --- a/proverclient/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package proverclient - -// Config represents the configuration of the prover clients -type Config struct { - // ProverURIs URIs to get access to the prover clients - ProverURIs []string `mapstructure:"ProverURIs"` -} diff --git a/proverclient/pb/zk_prover.pb.go b/proverclient/pb/zk_prover.pb.go deleted file mode 100644 index af2f4f39b3..0000000000 --- a/proverclient/pb/zk_prover.pb.go +++ /dev/null @@ -1,1669 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.6 -// source: zk_prover.proto - -package pb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type GetStatusResponse_StatusProver int32 - -const ( - GetStatusResponse_STATUS_PROVER_UNSPECIFIED GetStatusResponse_StatusProver = 0 - GetStatusResponse_STATUS_PROVER_BOOTING GetStatusResponse_StatusProver = 1 - GetStatusResponse_STATUS_PROVER_COMPUTING GetStatusResponse_StatusProver = 2 - GetStatusResponse_STATUS_PROVER_IDLE GetStatusResponse_StatusProver = 3 - GetStatusResponse_STATUS_PROVER_HALT GetStatusResponse_StatusProver = 4 -) - -// Enum value maps for GetStatusResponse_StatusProver. -var ( - GetStatusResponse_StatusProver_name = map[int32]string{ - 0: "STATUS_PROVER_UNSPECIFIED", - 1: "STATUS_PROVER_BOOTING", - 2: "STATUS_PROVER_COMPUTING", - 3: "STATUS_PROVER_IDLE", - 4: "STATUS_PROVER_HALT", - } - GetStatusResponse_StatusProver_value = map[string]int32{ - "STATUS_PROVER_UNSPECIFIED": 0, - "STATUS_PROVER_BOOTING": 1, - "STATUS_PROVER_COMPUTING": 2, - "STATUS_PROVER_IDLE": 3, - "STATUS_PROVER_HALT": 4, - } -) - -func (x GetStatusResponse_StatusProver) Enum() *GetStatusResponse_StatusProver { - p := new(GetStatusResponse_StatusProver) - *p = x - return p -} - -func (x GetStatusResponse_StatusProver) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GetStatusResponse_StatusProver) Descriptor() protoreflect.EnumDescriptor { - return file_zk_prover_proto_enumTypes[0].Descriptor() -} - -func (GetStatusResponse_StatusProver) Type() protoreflect.EnumType { - return &file_zk_prover_proto_enumTypes[0] -} - -func (x GetStatusResponse_StatusProver) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GetStatusResponse_StatusProver.Descriptor instead. -func (GetStatusResponse_StatusProver) EnumDescriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{5, 0} -} - -type GenProofResponse_ResultGenProof int32 - -const ( - GenProofResponse_RESULT_GEN_PROOF_UNSPECIFIED GenProofResponse_ResultGenProof = 0 - GenProofResponse_RESULT_GEN_PROOF_OK GenProofResponse_ResultGenProof = 1 - GenProofResponse_RESULT_GEN_PROOF_ERROR GenProofResponse_ResultGenProof = 2 - GenProofResponse_RESULT_GEN_PROOF_INTERNAL_ERROR GenProofResponse_ResultGenProof = 3 -) - -// Enum value maps for GenProofResponse_ResultGenProof. -var ( - GenProofResponse_ResultGenProof_name = map[int32]string{ - 0: "RESULT_GEN_PROOF_UNSPECIFIED", - 1: "RESULT_GEN_PROOF_OK", - 2: "RESULT_GEN_PROOF_ERROR", - 3: "RESULT_GEN_PROOF_INTERNAL_ERROR", - } - GenProofResponse_ResultGenProof_value = map[string]int32{ - "RESULT_GEN_PROOF_UNSPECIFIED": 0, - "RESULT_GEN_PROOF_OK": 1, - "RESULT_GEN_PROOF_ERROR": 2, - "RESULT_GEN_PROOF_INTERNAL_ERROR": 3, - } -) - -func (x GenProofResponse_ResultGenProof) Enum() *GenProofResponse_ResultGenProof { - p := new(GenProofResponse_ResultGenProof) - *p = x - return p -} - -func (x GenProofResponse_ResultGenProof) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GenProofResponse_ResultGenProof) Descriptor() protoreflect.EnumDescriptor { - return file_zk_prover_proto_enumTypes[1].Descriptor() -} - -func (GenProofResponse_ResultGenProof) Type() protoreflect.EnumType { - return &file_zk_prover_proto_enumTypes[1] -} - -func (x GenProofResponse_ResultGenProof) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GenProofResponse_ResultGenProof.Descriptor instead. -func (GenProofResponse_ResultGenProof) EnumDescriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{6, 0} -} - -type CancelResponse_ResultCancel int32 - -const ( - CancelResponse_RESULT_CANCEL_UNSPECIFIED CancelResponse_ResultCancel = 0 - CancelResponse_RESULT_CANCEL_OK CancelResponse_ResultCancel = 1 - CancelResponse_RESULT_CANCEL_ERROR CancelResponse_ResultCancel = 2 -) - -// Enum value maps for CancelResponse_ResultCancel. -var ( - CancelResponse_ResultCancel_name = map[int32]string{ - 0: "RESULT_CANCEL_UNSPECIFIED", - 1: "RESULT_CANCEL_OK", - 2: "RESULT_CANCEL_ERROR", - } - CancelResponse_ResultCancel_value = map[string]int32{ - "RESULT_CANCEL_UNSPECIFIED": 0, - "RESULT_CANCEL_OK": 1, - "RESULT_CANCEL_ERROR": 2, - } -) - -func (x CancelResponse_ResultCancel) Enum() *CancelResponse_ResultCancel { - p := new(CancelResponse_ResultCancel) - *p = x - return p -} - -func (x CancelResponse_ResultCancel) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (CancelResponse_ResultCancel) Descriptor() protoreflect.EnumDescriptor { - return file_zk_prover_proto_enumTypes[2].Descriptor() -} - -func (CancelResponse_ResultCancel) Type() protoreflect.EnumType { - return &file_zk_prover_proto_enumTypes[2] -} - -func (x CancelResponse_ResultCancel) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use CancelResponse_ResultCancel.Descriptor instead. -func (CancelResponse_ResultCancel) EnumDescriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{7, 0} -} - -type GetProofResponse_ResultGetProof int32 - -const ( - GetProofResponse_RESULT_GET_PROOF_UNSPECIFIED GetProofResponse_ResultGetProof = 0 - GetProofResponse_RESULT_GET_PROOF_COMPLETED_OK GetProofResponse_ResultGetProof = 1 - GetProofResponse_RESULT_GET_PROOF_ERROR GetProofResponse_ResultGetProof = 2 - GetProofResponse_RESULT_GET_PROOF_COMPLETED_ERROR GetProofResponse_ResultGetProof = 3 - GetProofResponse_RESULT_GET_PROOF_PENDING GetProofResponse_ResultGetProof = 4 - GetProofResponse_RESULT_GET_PROOF_INTERNAL_ERROR GetProofResponse_ResultGetProof = 5 - GetProofResponse_RESULT_GET_PROOF_CANCEL GetProofResponse_ResultGetProof = 6 -) - -// Enum value maps for GetProofResponse_ResultGetProof. -var ( - GetProofResponse_ResultGetProof_name = map[int32]string{ - 0: "RESULT_GET_PROOF_UNSPECIFIED", - 1: "RESULT_GET_PROOF_COMPLETED_OK", - 2: "RESULT_GET_PROOF_ERROR", - 3: "RESULT_GET_PROOF_COMPLETED_ERROR", - 4: "RESULT_GET_PROOF_PENDING", - 5: "RESULT_GET_PROOF_INTERNAL_ERROR", - 6: "RESULT_GET_PROOF_CANCEL", - } - GetProofResponse_ResultGetProof_value = map[string]int32{ - "RESULT_GET_PROOF_UNSPECIFIED": 0, - "RESULT_GET_PROOF_COMPLETED_OK": 1, - "RESULT_GET_PROOF_ERROR": 2, - "RESULT_GET_PROOF_COMPLETED_ERROR": 3, - "RESULT_GET_PROOF_PENDING": 4, - "RESULT_GET_PROOF_INTERNAL_ERROR": 5, - "RESULT_GET_PROOF_CANCEL": 6, - } -) - -func (x GetProofResponse_ResultGetProof) Enum() *GetProofResponse_ResultGetProof { - p := new(GetProofResponse_ResultGetProof) - *p = x - return p -} - -func (x GetProofResponse_ResultGetProof) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GetProofResponse_ResultGetProof) Descriptor() protoreflect.EnumDescriptor { - return file_zk_prover_proto_enumTypes[3].Descriptor() -} - -func (GetProofResponse_ResultGetProof) Type() protoreflect.EnumType { - return &file_zk_prover_proto_enumTypes[3] -} - -func (x GetProofResponse_ResultGetProof) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GetProofResponse_ResultGetProof.Descriptor instead. -func (GetProofResponse_ResultGetProof) EnumDescriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{8, 0} -} - -type Version struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - V0_0_1 string `protobuf:"bytes,1,opt,name=v0_0_1,json=v001,proto3" json:"v0_0_1,omitempty"` -} - -func (x *Version) Reset() { - *x = Version{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Version) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Version) ProtoMessage() {} - -func (x *Version) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Version.ProtoReflect.Descriptor instead. -func (*Version) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{0} -} - -func (x *Version) GetV0_0_1() string { - if x != nil { - return x.V0_0_1 - } - return "" -} - -//* -// @dev GetStatusRequest -type GetStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetStatusRequest) Reset() { - *x = GetStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetStatusRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetStatusRequest) ProtoMessage() {} - -func (x *GetStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetStatusRequest.ProtoReflect.Descriptor instead. -func (*GetStatusRequest) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{1} -} - -//* -// @dev GenProofRequest -// @param {input} - input prover -type GenProofRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Input *InputProver `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` -} - -func (x *GenProofRequest) Reset() { - *x = GenProofRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GenProofRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GenProofRequest) ProtoMessage() {} - -func (x *GenProofRequest) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GenProofRequest.ProtoReflect.Descriptor instead. -func (*GenProofRequest) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{2} -} - -func (x *GenProofRequest) GetInput() *InputProver { - if x != nil { - return x.Input - } - return nil -} - -//* -// @dev CancelRequest -// @param {id} - proof identifier -type CancelRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *CancelRequest) Reset() { - *x = CancelRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelRequest) ProtoMessage() {} - -func (x *CancelRequest) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelRequest.ProtoReflect.Descriptor instead. -func (*CancelRequest) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{3} -} - -func (x *CancelRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -//* -// @dev Request GetProof -// @param {id} - proof identifier -// @param {timeout} - time to wait until the service responds -type GetProofRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Timeout uint64 `protobuf:"varint,2,opt,name=timeout,proto3" json:"timeout,omitempty"` -} - -func (x *GetProofRequest) Reset() { - *x = GetProofRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetProofRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetProofRequest) ProtoMessage() {} - -func (x *GetProofRequest) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetProofRequest.ProtoReflect.Descriptor instead. -func (*GetProofRequest) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{4} -} - -func (x *GetProofRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *GetProofRequest) GetTimeout() uint64 { - if x != nil { - return x.Timeout - } - return 0 -} - -//* -// @dev Response GetStatus -// @param {state} - server state -// - BOOTING: being ready to compute proofs -// - COMPUTING: busy computing a proof -// - IDLE: waiting for a proof to compute -// - HALT: stop -// @param {last_computed_request_id} - last proof identifier that has been computed -// @param {last_computed_end_time} - last proof timestamp when it was finished -// @param {current_computing_request_id} - current proof identifier that ius being computed -// @param {current_computing_start_time} - current proof timestamp when it was started -// @param {version_proto} - .proto verion -// @param {version_server} - server version -// @param {pending_request_queue_ids} - list of pending proof identifier that are in the queue -type GetStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - State GetStatusResponse_StatusProver `protobuf:"varint,1,opt,name=state,proto3,enum=zkprover.v1.GetStatusResponse_StatusProver" json:"state,omitempty"` - LastComputedRequestId string `protobuf:"bytes,2,opt,name=last_computed_request_id,json=lastComputedRequestId,proto3" json:"last_computed_request_id,omitempty"` - LastComputedEndTime uint64 `protobuf:"varint,3,opt,name=last_computed_end_time,json=lastComputedEndTime,proto3" json:"last_computed_end_time,omitempty"` - CurrentComputingRequestId string `protobuf:"bytes,4,opt,name=current_computing_request_id,json=currentComputingRequestId,proto3" json:"current_computing_request_id,omitempty"` - CurrentComputingStartTime uint64 `protobuf:"varint,5,opt,name=current_computing_start_time,json=currentComputingStartTime,proto3" json:"current_computing_start_time,omitempty"` - VersionProto string `protobuf:"bytes,6,opt,name=version_proto,json=versionProto,proto3" json:"version_proto,omitempty"` - VersionServer string `protobuf:"bytes,7,opt,name=version_server,json=versionServer,proto3" json:"version_server,omitempty"` - PendingRequestQueueIds []string `protobuf:"bytes,8,rep,name=pending_request_queue_ids,json=pendingRequestQueueIds,proto3" json:"pending_request_queue_ids,omitempty"` -} - -func (x *GetStatusResponse) Reset() { - *x = GetStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetStatusResponse) ProtoMessage() {} - -func (x *GetStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetStatusResponse.ProtoReflect.Descriptor instead. -func (*GetStatusResponse) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{5} -} - -func (x *GetStatusResponse) GetState() GetStatusResponse_StatusProver { - if x != nil { - return x.State - } - return GetStatusResponse_STATUS_PROVER_UNSPECIFIED -} - -func (x *GetStatusResponse) GetLastComputedRequestId() string { - if x != nil { - return x.LastComputedRequestId - } - return "" -} - -func (x *GetStatusResponse) GetLastComputedEndTime() uint64 { - if x != nil { - return x.LastComputedEndTime - } - return 0 -} - -func (x *GetStatusResponse) GetCurrentComputingRequestId() string { - if x != nil { - return x.CurrentComputingRequestId - } - return "" -} - -func (x *GetStatusResponse) GetCurrentComputingStartTime() uint64 { - if x != nil { - return x.CurrentComputingStartTime - } - return 0 -} - -func (x *GetStatusResponse) GetVersionProto() string { - if x != nil { - return x.VersionProto - } - return "" -} - -func (x *GetStatusResponse) GetVersionServer() string { - if x != nil { - return x.VersionServer - } - return "" -} - -func (x *GetStatusResponse) GetPendingRequestQueueIds() []string { - if x != nil { - return x.PendingRequestQueueIds - } - return nil -} - -//* -// @dev Response GenProof -// @param {id} - proof identifier -// @param {result} - response result -// - OK: succesfull response -// - ERROR: request is not correct -// - INTERNAL_ERROR: server error when delivering the response -type GenProofResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Result GenProofResponse_ResultGenProof `protobuf:"varint,2,opt,name=result,proto3,enum=zkprover.v1.GenProofResponse_ResultGenProof" json:"result,omitempty"` -} - -func (x *GenProofResponse) Reset() { - *x = GenProofResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GenProofResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GenProofResponse) ProtoMessage() {} - -func (x *GenProofResponse) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GenProofResponse.ProtoReflect.Descriptor instead. -func (*GenProofResponse) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{6} -} - -func (x *GenProofResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *GenProofResponse) GetResult() GenProofResponse_ResultGenProof { - if x != nil { - return x.Result - } - return GenProofResponse_RESULT_GEN_PROOF_UNSPECIFIED -} - -//* -// @dev CancelResponse -// @param {result} - request result -// - OK: proof has been cancelled -// - ERROR: proof has not been cancelled -type CancelResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Result CancelResponse_ResultCancel `protobuf:"varint,1,opt,name=result,proto3,enum=zkprover.v1.CancelResponse_ResultCancel" json:"result,omitempty"` -} - -func (x *CancelResponse) Reset() { - *x = CancelResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CancelResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CancelResponse) ProtoMessage() {} - -func (x *CancelResponse) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CancelResponse.ProtoReflect.Descriptor instead. -func (*CancelResponse) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{7} -} - -func (x *CancelResponse) GetResult() CancelResponse_ResultCancel { - if x != nil { - return x.Result - } - return CancelResponse_RESULT_CANCEL_UNSPECIFIED -} - -//* -// @dev GetProofResponse -// @param {id} - proof identifier -// @param {proof} - groth16 proof -// @param {public} - public circuit inputs -// @param {result} - response result -// - COMPLETED_OK: proof has been computed successfully and it is valid -// - ERROR: request error -// - COMPLETED_ERROR: proof has been computed successfully and it is not valid -// - PENDING: proof is being computed -// - INTERNAL_ERROR: server error during proof computation -// - CANCEL: proof has been cancelled -// @param {result_string} - extends result information -type GetProofResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Proof *Proof `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - Public *PublicInputsExtended `protobuf:"bytes,3,opt,name=public,proto3" json:"public,omitempty"` - Result GetProofResponse_ResultGetProof `protobuf:"varint,4,opt,name=result,proto3,enum=zkprover.v1.GetProofResponse_ResultGetProof" json:"result,omitempty"` - ResultString string `protobuf:"bytes,5,opt,name=result_string,json=resultString,proto3" json:"result_string,omitempty"` -} - -func (x *GetProofResponse) Reset() { - *x = GetProofResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetProofResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetProofResponse) ProtoMessage() {} - -func (x *GetProofResponse) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetProofResponse.ProtoReflect.Descriptor instead. -func (*GetProofResponse) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{8} -} - -func (x *GetProofResponse) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *GetProofResponse) GetProof() *Proof { - if x != nil { - return x.Proof - } - return nil -} - -func (x *GetProofResponse) GetPublic() *PublicInputsExtended { - if x != nil { - return x.Public - } - return nil -} - -func (x *GetProofResponse) GetResult() GetProofResponse_ResultGetProof { - if x != nil { - return x.Result - } - return GetProofResponse_RESULT_GET_PROOF_UNSPECIFIED -} - -func (x *GetProofResponse) GetResultString() string { - if x != nil { - return x.ResultString - } - return "" -} - -// -// @dev PublicInputs -// @param {old_state_root} -// @param {old_local_exit_root} -// @param {new_state_root} -// @param {new_local_exit_root} -// @param {sequencer_addr} -// @param {batch_hash_data} -// @param {batch_num} -// @param {eth_timestamp} -type PublicInputs struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - OldStateRoot string `protobuf:"bytes,1,opt,name=old_state_root,json=oldStateRoot,proto3" json:"old_state_root,omitempty"` - OldLocalExitRoot string `protobuf:"bytes,2,opt,name=old_local_exit_root,json=oldLocalExitRoot,proto3" json:"old_local_exit_root,omitempty"` - NewStateRoot string `protobuf:"bytes,3,opt,name=new_state_root,json=newStateRoot,proto3" json:"new_state_root,omitempty"` - NewLocalExitRoot string `protobuf:"bytes,4,opt,name=new_local_exit_root,json=newLocalExitRoot,proto3" json:"new_local_exit_root,omitempty"` - SequencerAddr string `protobuf:"bytes,5,opt,name=sequencer_addr,json=sequencerAddr,proto3" json:"sequencer_addr,omitempty"` - BatchHashData string `protobuf:"bytes,6,opt,name=batch_hash_data,json=batchHashData,proto3" json:"batch_hash_data,omitempty"` - BatchNum uint32 `protobuf:"varint,7,opt,name=batch_num,json=batchNum,proto3" json:"batch_num,omitempty"` - EthTimestamp uint64 `protobuf:"varint,8,opt,name=eth_timestamp,json=ethTimestamp,proto3" json:"eth_timestamp,omitempty"` - AggregatorAddr string `protobuf:"bytes,9,opt,name=aggregator_addr,json=aggregatorAddr,proto3" json:"aggregator_addr,omitempty"` - ChainId uint64 `protobuf:"varint,10,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` -} - -func (x *PublicInputs) Reset() { - *x = PublicInputs{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PublicInputs) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublicInputs) ProtoMessage() {} - -func (x *PublicInputs) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PublicInputs.ProtoReflect.Descriptor instead. -func (*PublicInputs) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{9} -} - -func (x *PublicInputs) GetOldStateRoot() string { - if x != nil { - return x.OldStateRoot - } - return "" -} - -func (x *PublicInputs) GetOldLocalExitRoot() string { - if x != nil { - return x.OldLocalExitRoot - } - return "" -} - -func (x *PublicInputs) GetNewStateRoot() string { - if x != nil { - return x.NewStateRoot - } - return "" -} - -func (x *PublicInputs) GetNewLocalExitRoot() string { - if x != nil { - return x.NewLocalExitRoot - } - return "" -} - -func (x *PublicInputs) GetSequencerAddr() string { - if x != nil { - return x.SequencerAddr - } - return "" -} - -func (x *PublicInputs) GetBatchHashData() string { - if x != nil { - return x.BatchHashData - } - return "" -} - -func (x *PublicInputs) GetBatchNum() uint32 { - if x != nil { - return x.BatchNum - } - return 0 -} - -func (x *PublicInputs) GetEthTimestamp() uint64 { - if x != nil { - return x.EthTimestamp - } - return 0 -} - -func (x *PublicInputs) GetAggregatorAddr() string { - if x != nil { - return x.AggregatorAddr - } - return "" -} - -func (x *PublicInputs) GetChainId() uint64 { - if x != nil { - return x.ChainId - } - return 0 -} - -//* -// @dev ProofB -// @param {proofs} - two elliptic curves points -type ProofB struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Proofs []string `protobuf:"bytes,1,rep,name=proofs,proto3" json:"proofs,omitempty"` -} - -func (x *ProofB) Reset() { - *x = ProofB{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProofB) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProofB) ProtoMessage() {} - -func (x *ProofB) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProofB.ProtoReflect.Descriptor instead. -func (*ProofB) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{10} -} - -func (x *ProofB) GetProofs() []string { - if x != nil { - return x.Proofs - } - return nil -} - -//* -// @dev Proof -// @param {proof_a} - elliptic curve point -// @param {proof_b} - two elliptic curves points -// @param {proof_c} - elliptic curve point -type Proof struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ProofA []string `protobuf:"bytes,1,rep,name=proof_a,json=proofA,proto3" json:"proof_a,omitempty"` - ProofB []*ProofB `protobuf:"bytes,2,rep,name=proof_b,json=proofB,proto3" json:"proof_b,omitempty"` - ProofC []string `protobuf:"bytes,3,rep,name=proof_c,json=proofC,proto3" json:"proof_c,omitempty"` -} - -func (x *Proof) Reset() { - *x = Proof{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Proof) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Proof) ProtoMessage() {} - -func (x *Proof) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Proof.ProtoReflect.Descriptor instead. -func (*Proof) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{11} -} - -func (x *Proof) GetProofA() []string { - if x != nil { - return x.ProofA - } - return nil -} - -func (x *Proof) GetProofB() []*ProofB { - if x != nil { - return x.ProofB - } - return nil -} - -func (x *Proof) GetProofC() []string { - if x != nil { - return x.ProofC - } - return nil -} - -//* -// @dev InputProver -// @param {public_inputs} - public inputs -// @param {global_exit_root} - bridge global exit root -// @param {batch_l2_data} - contract calldata -// @param {address_aggregator} - ethereum address aggregator -// @param {db} - database containing all key-values in smt matching the old state root -// @param {contracts_bytecode} - key is the hash(contractBytecode), value is the bytecode itself -type InputProver struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PublicInputs *PublicInputs `protobuf:"bytes,1,opt,name=public_inputs,json=publicInputs,proto3" json:"public_inputs,omitempty"` - GlobalExitRoot string `protobuf:"bytes,2,opt,name=global_exit_root,json=globalExitRoot,proto3" json:"global_exit_root,omitempty"` - BatchL2Data string `protobuf:"bytes,3,opt,name=batch_l2_data,json=batchL2Data,proto3" json:"batch_l2_data,omitempty"` - Db map[string]string `protobuf:"bytes,4,rep,name=db,proto3" json:"db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production - ContractsBytecode map[string]string `protobuf:"bytes,5,rep,name=contracts_bytecode,json=contractsBytecode,proto3" json:"contracts_bytecode,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production -} - -func (x *InputProver) Reset() { - *x = InputProver{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InputProver) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InputProver) ProtoMessage() {} - -func (x *InputProver) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InputProver.ProtoReflect.Descriptor instead. -func (*InputProver) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{12} -} - -func (x *InputProver) GetPublicInputs() *PublicInputs { - if x != nil { - return x.PublicInputs - } - return nil -} - -func (x *InputProver) GetGlobalExitRoot() string { - if x != nil { - return x.GlobalExitRoot - } - return "" -} - -func (x *InputProver) GetBatchL2Data() string { - if x != nil { - return x.BatchL2Data - } - return "" -} - -func (x *InputProver) GetDb() map[string]string { - if x != nil { - return x.Db - } - return nil -} - -func (x *InputProver) GetContractsBytecode() map[string]string { - if x != nil { - return x.ContractsBytecode - } - return nil -} - -//* -// @dev PublicInputsExtended -// @param {public_inputs} - public inputs -// @param {input_hash} - global hash of all public inputs. Used as a sanity check. -type PublicInputsExtended struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PublicInputs *PublicInputs `protobuf:"bytes,1,opt,name=public_inputs,json=publicInputs,proto3" json:"public_inputs,omitempty"` - InputHash string `protobuf:"bytes,2,opt,name=input_hash,json=inputHash,proto3" json:"input_hash,omitempty"` -} - -func (x *PublicInputsExtended) Reset() { - *x = PublicInputsExtended{} - if protoimpl.UnsafeEnabled { - mi := &file_zk_prover_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PublicInputsExtended) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublicInputsExtended) ProtoMessage() {} - -func (x *PublicInputsExtended) ProtoReflect() protoreflect.Message { - mi := &file_zk_prover_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PublicInputsExtended.ProtoReflect.Descriptor instead. -func (*PublicInputsExtended) Descriptor() ([]byte, []int) { - return file_zk_prover_proto_rawDescGZIP(), []int{13} -} - -func (x *PublicInputsExtended) GetPublicInputs() *PublicInputs { - if x != nil { - return x.PublicInputs - } - return nil -} - -func (x *PublicInputsExtended) GetInputHash() string { - if x != nil { - return x.InputHash - } - return "" -} - -var File_zk_prover_proto protoreflect.FileDescriptor - -var file_zk_prover_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x7a, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x0b, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0x1f, - 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x06, 0x76, 0x30, 0x5f, - 0x30, 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x76, 0x30, 0x30, 0x31, 0x22, - 0x12, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x41, 0x0a, 0x0f, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, - 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x1f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x22, 0xe5, 0x04, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x7a, 0x6b, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, - 0x18, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x15, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x3f, 0x0a, 0x1c, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x25, 0x0a, 0x0e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x19, 0x70, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x71, 0x75, 0x65, - 0x75, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x70, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x51, 0x75, 0x65, 0x75, - 0x65, 0x49, 0x64, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, - 0x72, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x50, 0x52, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, - 0x52, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, - 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x52, - 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x49, 0x44, - 0x4c, 0x45, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, - 0x52, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x48, 0x41, 0x4c, 0x54, 0x10, 0x04, 0x22, 0xf7, 0x01, 0x0a, - 0x10, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x44, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x2c, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, - 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, - 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, - 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, - 0x47, 0x45, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x4e, 0x5f, - 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0xb0, 0x01, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x7a, 0x6b, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x5c, 0x0a, 0x0c, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x19, 0x52, - 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, - 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x5f, 0x4f, 0x4b, 0x10, 0x01, - 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, - 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x22, 0xec, 0x03, 0x0a, 0x10, 0x47, 0x65, - 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x28, - 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, - 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x06, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x12, 0x44, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0xf7, - 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, - 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, - 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, - 0x44, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x54, - 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x53, 0x55, - 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x50, 0x45, 0x4e, - 0x44, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, - 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, - 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x1b, 0x0a, 0x17, 0x52, - 0x45, 0x53, 0x55, 0x4c, 0x54, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, - 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x10, 0x06, 0x22, 0x8d, 0x03, 0x0a, 0x0c, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x6f, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x2d, 0x0a, 0x13, 0x6f, 0x6c, 0x64, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, - 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x6c, - 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x24, - 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, - 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x71, - 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x12, - 0x23, 0x0a, 0x0d, 0x65, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x65, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, - 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x20, 0x0a, 0x06, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x42, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x22, 0x67, 0x0a, 0x05, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x61, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x41, 0x12, 0x2c, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x5f, 0x62, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x42, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x5f, 0x63, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x43, 0x22, 0xaa, 0x03, 0x0a, 0x0b, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, - 0x76, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x7a, 0x6b, 0x70, - 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x73, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, - 0x75, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, - 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x22, 0x0a, - 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x32, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x32, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x30, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, - 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x02, 0x64, 0x62, 0x12, 0x5e, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, - 0x6f, 0x64, 0x65, 0x1a, 0x35, 0x0a, 0x07, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x75, 0x0a, 0x14, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x48, 0x61, 0x73, 0x68, 0x32, 0xbe, 0x02, 0x0a, 0x0f, 0x5a, 0x4b, 0x50, 0x72, - 0x6f, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x47, - 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, - 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x08, 0x47, 0x65, 0x6e, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1c, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x06, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x12, 0x1a, - 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x7a, 0x6b, 0x70, - 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x08, 0x47, 0x65, 0x74, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1c, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x7a, 0x6b, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, - 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, - 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_zk_prover_proto_rawDescOnce sync.Once - file_zk_prover_proto_rawDescData = file_zk_prover_proto_rawDesc -) - -func file_zk_prover_proto_rawDescGZIP() []byte { - file_zk_prover_proto_rawDescOnce.Do(func() { - file_zk_prover_proto_rawDescData = protoimpl.X.CompressGZIP(file_zk_prover_proto_rawDescData) - }) - return file_zk_prover_proto_rawDescData -} - -var file_zk_prover_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_zk_prover_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_zk_prover_proto_goTypes = []interface{}{ - (GetStatusResponse_StatusProver)(0), // 0: zkprover.v1.GetStatusResponse.StatusProver - (GenProofResponse_ResultGenProof)(0), // 1: zkprover.v1.GenProofResponse.ResultGenProof - (CancelResponse_ResultCancel)(0), // 2: zkprover.v1.CancelResponse.ResultCancel - (GetProofResponse_ResultGetProof)(0), // 3: zkprover.v1.GetProofResponse.ResultGetProof - (*Version)(nil), // 4: zkprover.v1.Version - (*GetStatusRequest)(nil), // 5: zkprover.v1.GetStatusRequest - (*GenProofRequest)(nil), // 6: zkprover.v1.GenProofRequest - (*CancelRequest)(nil), // 7: zkprover.v1.CancelRequest - (*GetProofRequest)(nil), // 8: zkprover.v1.GetProofRequest - (*GetStatusResponse)(nil), // 9: zkprover.v1.GetStatusResponse - (*GenProofResponse)(nil), // 10: zkprover.v1.GenProofResponse - (*CancelResponse)(nil), // 11: zkprover.v1.CancelResponse - (*GetProofResponse)(nil), // 12: zkprover.v1.GetProofResponse - (*PublicInputs)(nil), // 13: zkprover.v1.PublicInputs - (*ProofB)(nil), // 14: zkprover.v1.ProofB - (*Proof)(nil), // 15: zkprover.v1.Proof - (*InputProver)(nil), // 16: zkprover.v1.InputProver - (*PublicInputsExtended)(nil), // 17: zkprover.v1.PublicInputsExtended - nil, // 18: zkprover.v1.InputProver.DbEntry - nil, // 19: zkprover.v1.InputProver.ContractsBytecodeEntry -} -var file_zk_prover_proto_depIdxs = []int32{ - 16, // 0: zkprover.v1.GenProofRequest.input:type_name -> zkprover.v1.InputProver - 0, // 1: zkprover.v1.GetStatusResponse.state:type_name -> zkprover.v1.GetStatusResponse.StatusProver - 1, // 2: zkprover.v1.GenProofResponse.result:type_name -> zkprover.v1.GenProofResponse.ResultGenProof - 2, // 3: zkprover.v1.CancelResponse.result:type_name -> zkprover.v1.CancelResponse.ResultCancel - 15, // 4: zkprover.v1.GetProofResponse.proof:type_name -> zkprover.v1.Proof - 17, // 5: zkprover.v1.GetProofResponse.public:type_name -> zkprover.v1.PublicInputsExtended - 3, // 6: zkprover.v1.GetProofResponse.result:type_name -> zkprover.v1.GetProofResponse.ResultGetProof - 14, // 7: zkprover.v1.Proof.proof_b:type_name -> zkprover.v1.ProofB - 13, // 8: zkprover.v1.InputProver.public_inputs:type_name -> zkprover.v1.PublicInputs - 18, // 9: zkprover.v1.InputProver.db:type_name -> zkprover.v1.InputProver.DbEntry - 19, // 10: zkprover.v1.InputProver.contracts_bytecode:type_name -> zkprover.v1.InputProver.ContractsBytecodeEntry - 13, // 11: zkprover.v1.PublicInputsExtended.public_inputs:type_name -> zkprover.v1.PublicInputs - 5, // 12: zkprover.v1.ZKProverService.GetStatus:input_type -> zkprover.v1.GetStatusRequest - 6, // 13: zkprover.v1.ZKProverService.GenProof:input_type -> zkprover.v1.GenProofRequest - 7, // 14: zkprover.v1.ZKProverService.Cancel:input_type -> zkprover.v1.CancelRequest - 8, // 15: zkprover.v1.ZKProverService.GetProof:input_type -> zkprover.v1.GetProofRequest - 9, // 16: zkprover.v1.ZKProverService.GetStatus:output_type -> zkprover.v1.GetStatusResponse - 10, // 17: zkprover.v1.ZKProverService.GenProof:output_type -> zkprover.v1.GenProofResponse - 11, // 18: zkprover.v1.ZKProverService.Cancel:output_type -> zkprover.v1.CancelResponse - 12, // 19: zkprover.v1.ZKProverService.GetProof:output_type -> zkprover.v1.GetProofResponse - 16, // [16:20] is the sub-list for method output_type - 12, // [12:16] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name -} - -func init() { file_zk_prover_proto_init() } -func file_zk_prover_proto_init() { - if File_zk_prover_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_zk_prover_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Version); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenProofRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProofRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenProofResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CancelResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProofResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublicInputs); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProofB); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Proof); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InputProver); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_zk_prover_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublicInputsExtended); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_zk_prover_proto_rawDesc, - NumEnums: 4, - NumMessages: 16, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_zk_prover_proto_goTypes, - DependencyIndexes: file_zk_prover_proto_depIdxs, - EnumInfos: file_zk_prover_proto_enumTypes, - MessageInfos: file_zk_prover_proto_msgTypes, - }.Build() - File_zk_prover_proto = out.File - file_zk_prover_proto_rawDesc = nil - file_zk_prover_proto_goTypes = nil - file_zk_prover_proto_depIdxs = nil -} diff --git a/proverclient/pb/zk_prover_grpc.pb.go b/proverclient/pb/zk_prover_grpc.pb.go deleted file mode 100644 index a5c5ec4de3..0000000000 --- a/proverclient/pb/zk_prover_grpc.pb.go +++ /dev/null @@ -1,246 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.6 -// source: zk_prover.proto - -package pb - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// ZKProverServiceClient is the client API for ZKProverService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type ZKProverServiceClient interface { - GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) - GenProof(ctx context.Context, in *GenProofRequest, opts ...grpc.CallOption) (*GenProofResponse, error) - Cancel(ctx context.Context, in *CancelRequest, opts ...grpc.CallOption) (*CancelResponse, error) - GetProof(ctx context.Context, opts ...grpc.CallOption) (ZKProverService_GetProofClient, error) -} - -type zKProverServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewZKProverServiceClient(cc grpc.ClientConnInterface) ZKProverServiceClient { - return &zKProverServiceClient{cc} -} - -func (c *zKProverServiceClient) GetStatus(ctx context.Context, in *GetStatusRequest, opts ...grpc.CallOption) (*GetStatusResponse, error) { - out := new(GetStatusResponse) - err := c.cc.Invoke(ctx, "/zkprover.v1.ZKProverService/GetStatus", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *zKProverServiceClient) GenProof(ctx context.Context, in *GenProofRequest, opts ...grpc.CallOption) (*GenProofResponse, error) { - out := new(GenProofResponse) - err := c.cc.Invoke(ctx, "/zkprover.v1.ZKProverService/GenProof", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *zKProverServiceClient) Cancel(ctx context.Context, in *CancelRequest, opts ...grpc.CallOption) (*CancelResponse, error) { - out := new(CancelResponse) - err := c.cc.Invoke(ctx, "/zkprover.v1.ZKProverService/Cancel", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *zKProverServiceClient) GetProof(ctx context.Context, opts ...grpc.CallOption) (ZKProverService_GetProofClient, error) { - stream, err := c.cc.NewStream(ctx, &ZKProverService_ServiceDesc.Streams[0], "/zkprover.v1.ZKProverService/GetProof", opts...) - if err != nil { - return nil, err - } - x := &zKProverServiceGetProofClient{stream} - return x, nil -} - -type ZKProverService_GetProofClient interface { - Send(*GetProofRequest) error - Recv() (*GetProofResponse, error) - grpc.ClientStream -} - -type zKProverServiceGetProofClient struct { - grpc.ClientStream -} - -func (x *zKProverServiceGetProofClient) Send(m *GetProofRequest) error { - return x.ClientStream.SendMsg(m) -} - -func (x *zKProverServiceGetProofClient) Recv() (*GetProofResponse, error) { - m := new(GetProofResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// ZKProverServiceServer is the server API for ZKProverService service. -// All implementations must embed UnimplementedZKProverServiceServer -// for forward compatibility -type ZKProverServiceServer interface { - GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) - GenProof(context.Context, *GenProofRequest) (*GenProofResponse, error) - Cancel(context.Context, *CancelRequest) (*CancelResponse, error) - GetProof(ZKProverService_GetProofServer) error - mustEmbedUnimplementedZKProverServiceServer() -} - -// UnimplementedZKProverServiceServer must be embedded to have forward compatible implementations. -type UnimplementedZKProverServiceServer struct { -} - -func (UnimplementedZKProverServiceServer) GetStatus(context.Context, *GetStatusRequest) (*GetStatusResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetStatus not implemented") -} -func (UnimplementedZKProverServiceServer) GenProof(context.Context, *GenProofRequest) (*GenProofResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GenProof not implemented") -} -func (UnimplementedZKProverServiceServer) Cancel(context.Context, *CancelRequest) (*CancelResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Cancel not implemented") -} -func (UnimplementedZKProverServiceServer) GetProof(ZKProverService_GetProofServer) error { - return status.Errorf(codes.Unimplemented, "method GetProof not implemented") -} -func (UnimplementedZKProverServiceServer) mustEmbedUnimplementedZKProverServiceServer() {} - -// UnsafeZKProverServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to ZKProverServiceServer will -// result in compilation errors. -type UnsafeZKProverServiceServer interface { - mustEmbedUnimplementedZKProverServiceServer() -} - -func RegisterZKProverServiceServer(s grpc.ServiceRegistrar, srv ZKProverServiceServer) { - s.RegisterService(&ZKProverService_ServiceDesc, srv) -} - -func _ZKProverService_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetStatusRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ZKProverServiceServer).GetStatus(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/zkprover.v1.ZKProverService/GetStatus", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ZKProverServiceServer).GetStatus(ctx, req.(*GetStatusRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ZKProverService_GenProof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GenProofRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ZKProverServiceServer).GenProof(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/zkprover.v1.ZKProverService/GenProof", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ZKProverServiceServer).GenProof(ctx, req.(*GenProofRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ZKProverService_Cancel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CancelRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ZKProverServiceServer).Cancel(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/zkprover.v1.ZKProverService/Cancel", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ZKProverServiceServer).Cancel(ctx, req.(*CancelRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _ZKProverService_GetProof_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(ZKProverServiceServer).GetProof(&zKProverServiceGetProofServer{stream}) -} - -type ZKProverService_GetProofServer interface { - Send(*GetProofResponse) error - Recv() (*GetProofRequest, error) - grpc.ServerStream -} - -type zKProverServiceGetProofServer struct { - grpc.ServerStream -} - -func (x *zKProverServiceGetProofServer) Send(m *GetProofResponse) error { - return x.ServerStream.SendMsg(m) -} - -func (x *zKProverServiceGetProofServer) Recv() (*GetProofRequest, error) { - m := new(GetProofRequest) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// ZKProverService_ServiceDesc is the grpc.ServiceDesc for ZKProverService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var ZKProverService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "zkprover.v1.ZKProverService", - HandlerType: (*ZKProverServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetStatus", - Handler: _ZKProverService_GetStatus_Handler, - }, - { - MethodName: "GenProof", - Handler: _ZKProverService_GenProof_Handler, - }, - { - MethodName: "Cancel", - Handler: _ZKProverService_Cancel_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "GetProof", - Handler: _ZKProverService_GetProof_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, - Metadata: "zk_prover.proto", -} diff --git a/scripts/uniswap/main.go b/scripts/uniswap/main.go deleted file mode 100644 index a7e4e84190..0000000000 --- a/scripts/uniswap/main.go +++ /dev/null @@ -1,312 +0,0 @@ -package main - -// import ( -// "context" -// "fmt" -// "math/big" -// "strings" -// "time" - -// "github.com/0xPolygonHermez/zkevm-node/encoding" -// "github.com/0xPolygonHermez/zkevm-node/log" -// ERC20 "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" -// WETH "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/WETH" -// "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/core/UniswapV2Factory" -// "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/core/UniswapV2Pair" -// "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall" -// "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02" -// "github.com/0xPolygonHermez/zkevm-node/test/operations" -// "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" -// ) - -// const ( -// networkURL = "http://localhost:8123" -// pk = "0xdfd01798f92667dbf91df722434e8fbe96af0211d4d1b82bbbbc8f1def7a814f" -// txTimeout = 60 * time.Second -// ) - -// func main() { -// ctx := context.Background() - -// // if you want to test using goerli network -// // pk := "" // replace this by your goerli account private key -// // networkURL := "" // replace this by your goerli infura url - -// log.Infof("connecting to %v", networkURL) -// client, err := ethclient.Dial(networkURL) -// chkErr(err) -// log.Infof("connected") - -// chainID, err := client.ChainID(ctx) -// chkErr(err) -// log.Infof("chainID: %v", chainID) - -// auth := getAuth(ctx, client, pk) -// fmt.Println() - -// balance, err := client.BalanceAt(ctx, auth.From, nil) -// chkErr(err) - -// log.Debugf("ETH Balance for %v: %v", auth.From, balance) - -// // Deploy ERC20 Tokens to be swapped -// aCoinAddr, aCoin := deployERC20(auth, client, "A COIN", "ACO") -// fmt.Println() -// bCoinAddr, bCoin := deployERC20(auth, client, "B COIN", "BCO") -// fmt.Println() -// cCoinAddr, cCoin := deployERC20(auth, client, "C COIN", "CCO") -// fmt.Println() - -// // Deploy wETH Token, it's required by uniswap to swap ETH by tokens -// log.Debugf("Deploying wEth SC") -// wEthAddr, tx, wethSC, err := WETH.DeployWETH(auth, client) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("wEth SC tx: %v", tx.Hash().Hex()) -// log.Debugf("wEth SC addr: %v", wEthAddr.Hex()) -// fmt.Println() - -// // Deploy Uniswap Factory -// log.Debugf("Deploying Uniswap Factory") -// factoryAddr, tx, factory, err := UniswapV2Factory.DeployUniswapV2Factory(auth, client, auth.From) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("Uniswap Factory SC tx: %v", tx.Hash().Hex()) -// log.Debugf("Uniswap Factory SC addr: %v", factoryAddr.Hex()) -// fmt.Println() - -// // Deploy Uniswap Router -// log.Debugf("Deploying Uniswap Router") -// routerAddr, tx, router, err := UniswapV2Router02.DeployUniswapV2Router02(auth, client, factoryAddr, wEthAddr) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("Uniswap Router SC tx: %v", tx.Hash().Hex()) -// log.Debugf("Uniswap Router SC addr: %v", routerAddr.Hex()) -// fmt.Println() - -// // Deploy Uniswap Interface Multicall -// log.Debugf("Deploying Uniswap Multicall") -// multicallAddr, tx, _, err := UniswapInterfaceMulticall.DeployUniswapInterfaceMulticall(auth, client) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("Uniswap Interface Multicall SC tx: %v", tx.Hash().Hex()) -// log.Debugf("Uniswap Interface Multicall SC addr: %v", multicallAddr.Hex()) -// fmt.Println() - -// // Mint balance to tokens -// log.Debugf("Minting ERC20 Tokens") -// aMintAmount := "1000000000000000000000" -// tx = mintERC20(auth, client, aCoin, aMintAmount) -// log.Debugf("Mint A Coin tx: %v", tx.Hash().Hex()) -// fmt.Println() -// bMintAmount := "1000000000000000000000" -// tx = mintERC20(auth, client, bCoin, bMintAmount) -// log.Debugf("Mint B Coin tx: %v", tx.Hash().Hex()) -// fmt.Println() -// cMintAmount := "1000000000000000000000" -// tx = mintERC20(auth, client, cCoin, cMintAmount) -// log.Debugf("Mint C Coin tx: %v", tx.Hash().Hex()) -// fmt.Println() - -// // wrapping eth -// wethDepositoAmount := "20000000000000000" -// log.Debugf("Depositing %v ETH for account %v on token wEth", wethDepositoAmount, auth.From) -// wAuth := getAuth(ctx, client, pk) -// wAuth.Value, _ = big.NewInt(0).SetString(wethDepositoAmount, encoding.Base10) -// tx, err = wethSC.Deposit(auth) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) - -// value, err := aCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before allowance aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before allowance bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before allowance cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) - -// // Add allowance -// approveERC20(auth, client, aCoin, routerAddr, aMintAmount) -// fmt.Println() -// approveERC20(auth, client, bCoin, routerAddr, bMintAmount) -// fmt.Println() -// approveERC20(auth, client, cCoin, routerAddr, cMintAmount) -// fmt.Println() -// approveERC20(auth, client, wethSC, routerAddr, wethDepositoAmount) -// fmt.Println() - -// const liquidityAmount = "10000000000000000000" - -// value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity A, B aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity A, B bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity A, B cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) - -// // Add liquidity to the pool -// tx = addLiquidity(auth, client, router, aCoinAddr, bCoinAddr, liquidityAmount) -// log.Debugf("Add Liquidity to Pair A <-> B tx: %v", tx.Hash().Hex()) -// fmt.Println() - -// value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity B, C aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity B, C bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before adding liquidity B, C cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) - -// tx = addLiquidity(auth, client, router, bCoinAddr, cCoinAddr, liquidityAmount) -// log.Debugf("Add Liquidity to Pair B <-> C tx: %v", tx.Hash().Hex()) -// fmt.Println() - -// // Execute swaps -// const swapExactAmountInNumber = 1000000000000000000 -// swapExactAmountIn := big.NewInt(swapExactAmountInNumber) - -// value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before first swap aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before first swap bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("before first swap cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) - -// log.Debugf("Swaping tokens from A <-> B") -// swapExactTokensForTokens(auth, client, factory, router, aCoinAddr, bCoinAddr, swapExactAmountIn) -// fmt.Println() - -// value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("after first swap aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("after first swap bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) -// value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) -// chkErr(err) -// log.Debugf("after first swap cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) - -// log.Debugf("Swaping tokens from B <-> C") -// swapExactTokensForTokens(auth, client, factory, router, bCoinAddr, cCoinAddr, swapExactAmountIn) -// fmt.Println() -// } - -// func swapExactTokensForTokens(auth *bind.TransactOpts, client *ethclient.Client, -// factory *UniswapV2Factory.UniswapV2Factory, router *UniswapV2Router02.UniswapV2Router02, -// tokenA, tokenB common.Address, exactAmountIn *big.Int) { -// logPrefix := fmt.Sprintf("swapExactTokensForTokens %v <-> %v", tokenA.Hex(), tokenB.Hex()) - -// pairAddr, err := factory.GetPair(nil, tokenA, tokenB) -// chkErr(err) -// log.Debug(logPrefix, " pair: ", pairAddr.Hex()) -// pairSC, err := UniswapV2Pair.NewUniswapV2Pair(pairAddr, client) -// chkErr(err) - -// pairReserves, err := pairSC.GetReserves(nil) -// chkErr(err) -// log.Debug(logPrefix, " reserves 0: ", pairReserves.Reserve0, " 1: ", pairReserves.Reserve1, " Block Timestamp: ", pairReserves.BlockTimestampLast) - -// amountOut, err := router.GetAmountOut(nil, exactAmountIn, pairReserves.Reserve0, pairReserves.Reserve1) -// chkErr(err) -// log.Debug(logPrefix, " exactAmountIn: ", exactAmountIn, " amountOut: ", amountOut) - -// tx, err := router.SwapExactTokensForTokens(auth, exactAmountIn, amountOut, []common.Address{tokenA, tokenB}, auth.From, getDeadline()) -// chkErr(err) -// log.Debug(logPrefix, " tx: ", tx.Hash().Hex()) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// } - -// func getAuth(ctx context.Context, client *ethclient.Client, pkHex string) *bind.TransactOpts { -// chainID, err := client.ChainID(ctx) -// chkErr(err) -// privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(pkHex, "0x")) -// chkErr(err) -// auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) -// chkErr(err) - -// return auth -// } - -// func deployERC20(auth *bind.TransactOpts, client *ethclient.Client, name, symbol string) (common.Address, *ERC20.ERC20) { -// log.Debugf("Deploying ERC20 Token: [%v]%v", symbol, name) -// addr, tx, instance, err := ERC20.DeployERC20(auth, client, name, symbol) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("%v SC tx: %v", name, tx.Hash().Hex()) -// log.Debugf("%v SC addr: %v", name, addr.Hex()) -// return addr, instance -// } - -// func mintERC20(auth *bind.TransactOpts, client *ethclient.Client, erc20sc *ERC20.ERC20, amount string) *types.Transaction { -// name, err := erc20sc.Name(nil) -// chkErr(err) -// log.Debugf("Minting %v tokens for account %v on token %v", amount, auth.From, name) -// mintAmount, _ := big.NewInt(0).SetString(amount, encoding.Base10) -// tx, err := erc20sc.Mint(auth, mintAmount) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// return tx -// } - -// func approveERC20(auth *bind.TransactOpts, client *ethclient.Client, -// sc interface { -// Name(opts *bind.CallOpts) (string, error) -// Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) -// }, -// routerAddr common.Address, -// amount string) { -// name, err := sc.Name(nil) -// chkErr(err) - -// a, _ := big.NewInt(0).SetString(amount, encoding.Base10) - -// log.Debugf("Approving %v tokens to be used by the router for %v on behalf of account %v", a.Text(encoding.Base10), name, auth.From) -// tx, err := sc.Approve(auth, routerAddr, a) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// log.Debugf("Approval %v tx: %v", name, tx.Hash().Hex()) -// } - -// func addLiquidity(auth *bind.TransactOpts, client *ethclient.Client, router *UniswapV2Router02.UniswapV2Router02, tokenA, tokenB common.Address, amount string) *types.Transaction { -// a, _ := big.NewInt(0).SetString(amount, encoding.Base10) -// log.Debugf("Adding liquidity(%v) for tokens A: %v, B:%v, Recipient: %v", amount, tokenA.Hex(), tokenB.Hex(), auth.From.Hex()) -// tx, err := router.AddLiquidity(auth, tokenA, tokenB, a, a, a, a, auth.From, getDeadline()) -// chkErr(err) -// err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) -// chkErr(err) -// return tx -// } - -// func getDeadline() *big.Int { -// const deadLinelimit = 5 * time.Minute -// return big.NewInt(time.Now().UTC().Add(deadLinelimit).Unix()) -// } - -// func chkErr(err error) { -// if err != nil { -// log.Fatal(err) -// } -// } diff --git a/sequencer/addrqueue.go b/sequencer/addrqueue.go new file mode 100644 index 0000000000..84d5e4e90d --- /dev/null +++ b/sequencer/addrqueue.go @@ -0,0 +1,196 @@ +package sequencer + +import ( + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" + "github.com/ethereum/go-ethereum/common" +) + +// addrQueue is a struct that stores the ready and notReady txs for a specific from address +type addrQueue struct { + from common.Address + fromStr string + currentNonce uint64 + currentBalance *big.Int + readyTx *TxTracker + notReadyTxs map[uint64]*TxTracker +} + +// newAddrQueue creates and init a addrQueue +func newAddrQueue(addr common.Address, nonce uint64, balance *big.Int) *addrQueue { + return &addrQueue{ + from: addr, + fromStr: addr.String(), + currentNonce: nonce, + currentBalance: balance, + readyTx: nil, + notReadyTxs: make(map[uint64]*TxTracker), + } +} + +// addTx adds a tx to the addrQueue and updates the ready a notReady Txs +func (a *addrQueue) addTx(tx *TxTracker) (newReadyTx, prevReadyTx *TxTracker, dropReason error) { + if a.currentNonce == tx.Nonce { // Is a possible readyTx + // We set the tx as readyTx if we do not have one assigned or if the gasPrice is better or equal than the current readyTx + if a.readyTx == nil || ((a.readyTx != nil) && (tx.GasPrice.Cmp(a.readyTx.GasPrice) >= 0)) { + oldReadyTx := a.readyTx + if a.currentBalance.Cmp(tx.Cost) >= 0 { // + a.readyTx = tx + return tx, oldReadyTx, nil + } else { // If there is not enough balance we set the new tx as notReadyTxs + a.readyTx = nil + a.notReadyTxs[tx.Nonce] = tx + return nil, oldReadyTx, nil + } + } + } else if a.currentNonce > tx.Nonce { + return nil, nil, runtime.ErrIntrinsicInvalidNonce + } + + nrTx, found := a.notReadyTxs[tx.Nonce] + if !found || ((found) && (tx.GasPrice.Cmp(nrTx.GasPrice) >= 0)) { + a.notReadyTxs[tx.Nonce] = tx + } + + return nil, nil, nil +} + +// ExpireTransactions removes the txs that have been in the queue for more than maxTime +func (a *addrQueue) ExpireTransactions(maxTime time.Duration) ([]*TxTracker, *TxTracker) { + var ( + txs []*TxTracker + prevReadyTx *TxTracker + ) + + for _, txTracker := range a.notReadyTxs { + if txTracker.ReceivedAt.Add(maxTime).Before(time.Now()) { + txs = append(txs, txTracker) + delete(a.notReadyTxs, txTracker.Nonce) + log.Debugf("Deleting notReadyTx %s from addrQueue %s", txTracker.HashStr, a.fromStr) + } + } + + if a.readyTx != nil && a.readyTx.ReceivedAt.Add(maxTime).Before(time.Now()) { + prevReadyTx = a.readyTx + txs = append(txs, a.readyTx) + a.readyTx = nil + log.Debugf("Deleting notReadyTx %s from addrQueue %s", prevReadyTx.HashStr, a.fromStr) + } + + return txs, prevReadyTx +} + +// IsEmpty returns true if the addrQueue is empty +func (a *addrQueue) IsEmpty() bool { + return a.readyTx == nil && len(a.notReadyTxs) == 0 +} + +// deleteTx deletes the tx from the addrQueue +func (a *addrQueue) deleteTx(txHash common.Hash) (deletedReadyTx *TxTracker) { + txHashStr := txHash.String() + + if (a.readyTx != nil) && (a.readyTx.HashStr == txHashStr) { + log.Infof("Deleting readyTx %s from addrQueue %s", txHashStr, a.fromStr) + prevReadyTx := a.readyTx + a.readyTx = nil + return prevReadyTx + } else { + for _, txTracker := range a.notReadyTxs { + if txTracker.HashStr == txHashStr { + log.Infof("Deleting notReadyTx %s from addrQueue %s", txHashStr, a.fromStr) + delete(a.notReadyTxs, txTracker.Nonce) + } + } + return nil + } +} + +// updateCurrentNonceBalance updates the nonce and balance of the addrQueue and updates the ready and notReady txs +func (a *addrQueue) updateCurrentNonceBalance(nonce *uint64, balance *big.Int) (newReadyTx, prevReadyTx *TxTracker, toDelete []*TxTracker) { + var oldReadyTx *TxTracker = nil + txsToDelete := make([]*TxTracker, 0) + + if balance != nil { + log.Infof("Updating balance for addrQueue %s from %s to %s", a.fromStr, a.currentBalance.String(), balance.String()) + a.currentBalance = balance + } + + if nonce != nil { + if a.currentNonce != *nonce { + a.currentNonce = *nonce + for _, txTracker := range a.notReadyTxs { + if txTracker.Nonce < a.currentNonce { + reason := runtime.ErrIntrinsicInvalidNonce.Error() + txTracker.FailedReason = &reason + txsToDelete = append(txsToDelete, txTracker) + } + } + for _, txTracker := range txsToDelete { + log.Infof("Deleting notReadyTx with nonce %d from addrQueue %s", txTracker.Nonce, a.fromStr) + delete(a.notReadyTxs, txTracker.Nonce) + } + } + } + + if a.readyTx != nil { + // If readyTX.nonce is not the currentNonce or currentBalance is less that the readyTx.Cost + // set readyTx=nil. Later we will move the tx to notReadyTxs + if (a.readyTx.Nonce != a.currentNonce) || (a.currentBalance.Cmp(a.readyTx.Cost) < 0) { + oldReadyTx = a.readyTx + a.readyTx = nil + } + } + + // We check if we have a new readyTx from the notReadyTxs (at this point, to optmize the code, + // we are not including the oldReadyTx in notReadyTxs, as it can match again if the nonce has not changed) + if a.readyTx == nil { + nrTx, found := a.notReadyTxs[a.currentNonce] + if found { + if a.currentBalance.Cmp(nrTx.Cost) >= 0 { + a.readyTx = nrTx + log.Infof("Moving notReadyTx %s to readyTx for addrQueue %s", nrTx.HashStr, a.fromStr) + delete(a.notReadyTxs, a.currentNonce) + } + } + } + + // We add the oldReadyTx to notReadyTxs (if it has a valid nonce) at this point to avoid check it again in the previous if statement + if oldReadyTx != nil && oldReadyTx.Nonce > a.currentNonce { + log.Infof("Marking readyTx %s as notReadyTx from addrQueue %s", oldReadyTx.HashStr, a.fromStr) + a.notReadyTxs[oldReadyTx.Nonce] = oldReadyTx + } + + return a.readyTx, oldReadyTx, txsToDelete +} + +// UpdateTxZKCounters updates the ZKCounters for the given tx (txHash) +// If the updated tx is the readyTx it returns a copy of the previous readyTx, nil otherwise +func (a *addrQueue) UpdateTxZKCounters(txHash common.Hash, counters state.ZKCounters, constraints batchConstraintsFloat64, weights batchResourceWeights) (newReadyTx, prevReadyTx *TxTracker) { + txHashStr := txHash.String() + + if (a.readyTx != nil) && (a.readyTx.HashStr == txHashStr) { + // We need to assign the new readyTx as a new TxTracker copy of the previous one with the updated efficiency + // We need to do in this way because the efficiency value is changed and we use this value as key field to + // add/delete TxTrackers in the efficiencyList + prevReadyTx := a.readyTx + newReadyTx := *a.readyTx + newReadyTx.updateZKCounters(counters, constraints, weights) + a.readyTx = &newReadyTx + log.Debugf("Updating readyTx %s with new ZKCounters from addrQueue %s", txHashStr, a.fromStr) + return a.readyTx, prevReadyTx + } else { + txHashStr := txHash.String() + for _, txTracker := range a.notReadyTxs { + if txTracker.HashStr == txHashStr { + log.Debugf("Updating notReadyTx %s with new ZKCounters from addrQueue %s", txHashStr, a.fromStr) + txTracker.updateZKCounters(counters, constraints, weights) + break + } + } + return nil, nil + } +} diff --git a/sequencer/addrqueue_test.go b/sequencer/addrqueue_test.go new file mode 100644 index 0000000000..2926af696d --- /dev/null +++ b/sequencer/addrqueue_test.go @@ -0,0 +1,153 @@ +package sequencer + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +type notReadyTx struct { + nonce uint64 + hash common.Hash +} + +type addrQueueAddTxTestCase struct { + name string + hash common.Hash + nonce uint64 + gasPrice *big.Int + cost *big.Int + expectedReadyTx common.Hash + expectedNotReadyTx []notReadyTx +} + +var addr addrQueue + +func newTestTxTracker(hash common.Hash, nonce uint64, gasPrice *big.Int, cost *big.Int) *TxTracker { + tx := TxTracker{Hash: hash, Nonce: nonce, GasPrice: gasPrice, Cost: cost} + tx.HashStr = tx.Hash.String() + return &tx +} + +func processAddTxTestCases(t *testing.T, testCases []addrQueueAddTxTestCase) { + var emptyHash common.Hash = common.Hash{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + tx := newTestTxTracker(tc.hash, tc.nonce, tc.gasPrice, tc.cost) + newReadyTx, _, _ := addr.addTx(tx) + if tc.expectedReadyTx.String() == emptyHash.String() { + if !(addr.readyTx == nil) { + t.Fatalf("Error readyTx. Expected=%s, Actual=%s", tc.expectedReadyTx, "") + } + if !(newReadyTx == nil) { + t.Fatalf("Error newReadyTx. Expected=nil, Actual=%s", newReadyTx.HashStr) + } + } else { + if !(addr.readyTx.Hash == tc.expectedReadyTx) { + t.Fatalf("Error readyTx. Expected=%s, Actual=%s", tc.expectedReadyTx, addr.readyTx.HashStr) + } + } + + for _, nr := range tc.expectedNotReadyTx { + txTmp, found := addr.notReadyTxs[nr.nonce] + if !(found) { + t.Fatalf("Error notReadyTx nonce=%d don't exists", nr.nonce) + } + if !(txTmp.Hash == nr.hash) { + t.Fatalf("Error notReadyTx nonce=%d. Expected=%s, Actual=%s", nr.nonce, nr.hash.String(), txTmp.HashStr) + } + } + }) + } +} + +func TestAddrQueue(t *testing.T) { + addr = addrQueue{fromStr: "0x99999", currentNonce: 1, currentBalance: new(big.Int).SetInt64(10), notReadyTxs: make(map[uint64]*TxTracker)} + + addTxTestCases := []addrQueueAddTxTestCase{ + { + name: "Add not ready tx 0x02", hash: common.Hash{0x2}, nonce: 2, gasPrice: new(big.Int).SetInt64(2), cost: new(big.Int).SetInt64(5), + expectedReadyTx: common.Hash{}, + expectedNotReadyTx: []notReadyTx{ + {nonce: 2, hash: common.Hash{0x2}}, + }, + }, + { + name: "Add ready tx 0x01", hash: common.Hash{0x1}, nonce: 1, gasPrice: new(big.Int).SetInt64(2), cost: new(big.Int).SetInt64(5), + expectedReadyTx: common.Hash{1}, + expectedNotReadyTx: []notReadyTx{ + {nonce: 2, hash: common.Hash{0x2}}, + }, + }, + { + name: "Add not ready tx 0x04", hash: common.Hash{0x4}, nonce: 4, gasPrice: new(big.Int).SetInt64(2), cost: new(big.Int).SetInt64(5), + expectedReadyTx: common.Hash{1}, + expectedNotReadyTx: []notReadyTx{ + {nonce: 2, hash: common.Hash{0x2}}, + {nonce: 4, hash: common.Hash{0x4}}, + }, + }, + { + name: "Replace tx with nonce 4 for tx 0x44 with best GasPrice", hash: common.Hash{0x44}, nonce: 4, gasPrice: new(big.Int).SetInt64(3), cost: new(big.Int).SetInt64(5), + expectedReadyTx: common.Hash{1}, + expectedNotReadyTx: []notReadyTx{ + {nonce: 2, hash: common.Hash{0x2}}, + {nonce: 4, hash: common.Hash{0x44}}, + }, + }, + } + + processAddTxTestCases(t, addTxTestCases) + + t.Run("Delete readyTx 0x01", func(t *testing.T) { + tc := addTxTestCases[1] + tx := newTestTxTracker(tc.hash, tc.nonce, tc.gasPrice, tc.cost) + deltx := addr.deleteTx(tx.Hash) + if !(addr.readyTx == nil) { + t.Fatalf("Error readyTx not nil. Expected=%s, Actual=%s", "", addr.readyTx.HashStr) + } + if !(deltx.HashStr == tx.HashStr) { + t.Fatalf("Error returning deletedReadyTx. Expected=%s, Actual=%s", tx.HashStr, deltx.HashStr) + } + }) + + processAddTxTestCases(t, []addrQueueAddTxTestCase{ + { + name: "Add tx with nonce = currentNonce but with cost > currentBalance", hash: common.Hash{0x11}, nonce: 1, gasPrice: new(big.Int).SetInt64(2), cost: new(big.Int).SetInt64(15), + expectedReadyTx: common.Hash{}, + expectedNotReadyTx: []notReadyTx{ + {nonce: 1, hash: common.Hash{0x11}}, + {nonce: 2, hash: common.Hash{0x2}}, + {nonce: 4, hash: common.Hash{0x44}}, + }, + }, + }) + + t.Run("Update currentBalance = 15, set tx 0x11 as ready", func(t *testing.T) { + tmpHash := common.Hash{0x11} + addr.updateCurrentNonceBalance(&addr.currentNonce, new(big.Int).SetInt64(15)) + if !(addr.readyTx != nil && addr.readyTx.Hash.String() == tmpHash.String()) { + t.Fatalf("Error readyTx. Expected=%s, Actual=%s", tmpHash, "") + } + + tx, found := addr.notReadyTxs[1] + + if found { + t.Fatalf("Error notReadyTx nonce=%d. Expected=%s, Actual=%s", addr.currentNonce, "", tx.Hash.String()) + } + }) + + t.Run("Update currentNonce = 4, set tx 0x04 as ready", func(t *testing.T) { + tmpHash := common.Hash{0x44} + newNonce := uint64(4) + addr.updateCurrentNonceBalance(&newNonce, new(big.Int).SetInt64(15)) + if !(addr.readyTx != nil && addr.readyTx.Hash.String() == tmpHash.String()) { + t.Fatalf("Error readyTx. Expected=%s, Actual=%s", tmpHash, addr.readyTx.Hash.String()) + } + + if len(addr.notReadyTxs) > 0 { + t.Fatalf("Error notReadyTx not empty. Expected=%d, Actual=%d", 0, len(addr.notReadyTxs)) + } + }) +} diff --git a/sequencer/batchbuilder.go b/sequencer/batchbuilder.go deleted file mode 100644 index 78cd6f2aa3..0000000000 --- a/sequencer/batchbuilder.go +++ /dev/null @@ -1,520 +0,0 @@ -package sequencer - -import ( - "context" - "errors" - "fmt" - "math" - "strings" - "time" - - "github.com/0xPolygonHermez/zkevm-node/etherman/types" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - ethTypes "github.com/ethereum/go-ethereum/core/types" - "github.com/jackc/pgx/v4" -) - -const ( - maxTxsPerBatch uint64 = 150 - maxBatchBytesSize int = 30000 -) - -type processTxResponse struct { - processedTxs []*state.ProcessTransactionResponse - processedTxsHashes []string - unprocessedTxs map[string]*state.ProcessTransactionResponse - unprocessedTxsHashes []string - isBatchProcessed bool -} - -func (s *Sequencer) tryToProcessTx(ctx context.Context, ticker *time.Ticker) { - // Check if synchronizer is up to date - if !s.isSynced(ctx) { - log.Info("wait for synchronizer to sync last batch") - waitTick(ctx, ticker) - return - } - log.Info("synchronizer has synced last batch, checking if current sequence should be closed") - - // Check if sequence should be close - log.Infof("checking if current sequence should be closed") - if s.shouldCloseSequenceInProgress(ctx) { - log.Infof("current sequence should be closed") - err := s.closeSequence(ctx) - if err != nil { - if strings.Contains(err.Error(), state.ErrClosingBatchWithoutTxs.Error()) { - log.Warn("Current batch has not been closed since it had no txs. Trying to add more txs to avoid death lock") - } else { - log.Errorf("error closing sequence: %w", err) - log.Info("resetting sequence in progress") - if err = s.loadSequenceFromState(ctx); err != nil { - log.Errorf("error loading sequence from state: %w", err) - } - return - } - } - } - - // backup current sequence - sequenceBeforeTryingToProcessNewTxs := types.Sequence{ - GlobalExitRoot: s.sequenceInProgress.GlobalExitRoot, - StateRoot: s.sequenceInProgress.StateRoot, - LocalExitRoot: s.sequenceInProgress.LocalExitRoot, - Timestamp: s.sequenceInProgress.Timestamp, - } - copy(sequenceBeforeTryingToProcessNewTxs.Txs, s.sequenceInProgress.Txs) - - getTxsLimit := maxTxsPerBatch - uint64(len(s.sequenceInProgress.Txs)) - - minGasPrice, err := s.gpe.GetAvgGasPrice(ctx) - if err != nil { - log.Errorf("failed to get avg gas price, err: %w", err) - return - } - - // get txs from the pool - appendedClaimsTxsAmount := s.appendPendingTxs(ctx, true, 0, getTxsLimit, ticker) - appendedTxsAmount := s.appendPendingTxs(ctx, false, minGasPrice.Uint64(), getTxsLimit-appendedClaimsTxsAmount, ticker) + appendedClaimsTxsAmount - - if appendedTxsAmount == 0 { - return - } - // clear txs if it bigger than expected - encodedTxsBytesSize := math.MaxInt - numberOfTxsInProcess := len(s.sequenceInProgress.Txs) - for encodedTxsBytesSize > maxBatchBytesSize && numberOfTxsInProcess > 0 { - encodedTxs, err := state.EncodeTransactions(s.sequenceInProgress.Txs) - if err != nil { - log.Errorf("failed to encode txs, err: %w", err) - return - } - encodedTxsBytesSize = len(encodedTxs) - - if encodedTxsBytesSize > maxBatchBytesSize && numberOfTxsInProcess > 0 { - // if only one tx overflows, than it means, tx is invalid - if numberOfTxsInProcess == 1 { - err = s.pool.UpdateTxStatus(ctx, s.sequenceInProgress.Txs[0].Hash(), pool.TxStatusInvalid) - for err != nil { - log.Errorf("failed to update tx with hash: %s to status: %s", - s.sequenceInProgress.Txs[0].Hash().String(), pool.TxStatusInvalid) - err = s.pool.UpdateTxStatus(ctx, s.sequenceInProgress.Txs[0].Hash(), pool.TxStatusInvalid) - waitTick(ctx, ticker) - } - } - log.Infof("decreasing amount of sent txs, bcs encodedTxsBytesSize > maxBatchBytesSize, encodedTxsBytesSize: %d, maxBatchBytesSize: %d", - encodedTxsBytesSize, maxBatchBytesSize) - s.sequenceInProgress.Txs = s.sequenceInProgress.Txs[:numberOfTxsInProcess-1] - s.isSequenceTooBig = true - numberOfTxsInProcess = len(s.sequenceInProgress.Txs) - } - } - - // process batch - log.Infof("processing batch with %d txs. %d txs are new from this iteration", len(s.sequenceInProgress.Txs), appendedTxsAmount) - processResponse, err := s.processTxs(ctx) - if err != nil { - s.sequenceInProgress = sequenceBeforeTryingToProcessNewTxs - log.Errorf("failed to process txs, err: %w", err) - return - } - - // reprocess the batch until: - // - all the txs in it are processed, so the batch doesn't include invalid txs - // - the batch is processed (certain situations may cause the entire batch to not have effect on the state) - unprocessedTxs := processResponse.unprocessedTxs - for !processResponse.isBatchProcessed || len(processResponse.unprocessedTxs) > 0 { - // include only processed txs in the sequence - s.sequenceInProgress.Txs = make([]ethTypes.Transaction, 0, len(processResponse.processedTxs)) - for i := 0; i < len(processResponse.processedTxs); i++ { - s.sequenceInProgress.Txs = append(s.sequenceInProgress.Txs, processResponse.processedTxs[i].Tx) - } - - if len(s.sequenceInProgress.Txs) == 0 { - log.Infof("sequence in progress doesn't have txs, no need to send a batch") - break - } - log.Infof("failed to process batch or invalid txs. Retrying with %d txs", len(s.sequenceInProgress.Txs)) - // reprocess - processResponse, err = s.processTxs(ctx) - if err != nil { - s.sequenceInProgress = sequenceBeforeTryingToProcessNewTxs - log.Errorf("failed to reprocess txs, err: %w", err) - return - } - if len(processResponse.processedTxsHashes) != 0 { - for _, hash := range processResponse.processedTxsHashes { - delete(unprocessedTxs, hash) - } - } - for _, txHash := range processResponse.unprocessedTxsHashes { - if _, ok := unprocessedTxs[txHash]; !ok { - unprocessedTxs[txHash] = processResponse.unprocessedTxs[txHash] - } - } - } - log.Infof("%d txs processed successfully", len(processResponse.processedTxsHashes)) - - // If after processing new txs the sequence is equal or smaller, revert changes and close sequence - if len(s.sequenceInProgress.Txs) <= len(sequenceBeforeTryingToProcessNewTxs.Txs) && len(s.sequenceInProgress.Txs) > 0 { - log.Infof( - "current sequence should be closed because after trying to add txs to it, it went from having %d valid txs to %d", - len(sequenceBeforeTryingToProcessNewTxs.Txs), len(s.sequenceInProgress.Txs), - ) - s.sequenceInProgress = sequenceBeforeTryingToProcessNewTxs - if err := s.closeSequence(ctx); err != nil { - log.Errorf("error closing sequence: %w", err) - } - return - } - - // only save in DB processed transactions. - err = s.storeProcessedTransactions(ctx, processResponse.processedTxs) - if err != nil { - s.sequenceInProgress = sequenceBeforeTryingToProcessNewTxs - log.Errorf("failed to store processed txs, err: %w", err) - return - } - log.Infof("%d txs stored and added into the trusted state", len(processResponse.processedTxs)) - - invalidTxsHashes, failedTxsHashes := s.splitInvalidAndFailedTxs(ctx, unprocessedTxs, ticker) - - // update processed txs - s.updateTxsStatus(ctx, ticker, processResponse.processedTxsHashes, pool.TxStatusSelected) - // update invalid txs - s.updateTxsStatus(ctx, ticker, invalidTxsHashes, pool.TxStatusInvalid) - // update failed txs - s.updateTxsStatus(ctx, ticker, failedTxsHashes, pool.TxStatusFailed) - // increment counter for failed txs - s.incrementFailedCounter(ctx, ticker, failedTxsHashes) -} - -func (s *Sequencer) splitInvalidAndFailedTxs(ctx context.Context, unprocessedTxs map[string]*state.ProcessTransactionResponse, ticker *time.Ticker) ([]string, []string) { - invalidTxsHashes := []string{} - failedTxsHashes := []string{} - for _, tx := range unprocessedTxs { - isTxNonceLessThanAccountNonce, err := s.isTxNonceLessThanAccountNonce(ctx, tx) - for err != nil { - log.Errorf("failed to compare account nonce and tx nonce, err: %w", err) - isTxNonceLessThanAccountNonce, err = s.isTxNonceLessThanAccountNonce(ctx, tx) - waitTick(ctx, ticker) - } - if isTxNonceLessThanAccountNonce { - log.Infof("tx with hash %s is invalid, account nonce > tx nonce") - invalidTxsHashes = append(invalidTxsHashes, tx.Tx.Hash().String()) - } else { - failedTxsHashes = append(failedTxsHashes, tx.Tx.Hash().String()) - } - } - - return invalidTxsHashes, failedTxsHashes -} - -func (s *Sequencer) updateTxsStatus(ctx context.Context, ticker *time.Ticker, hashes []string, status pool.TxStatus) { - err := s.pool.UpdateTxsStatus(ctx, hashes, status) - for err != nil { - log.Errorf("failed to update txs status to %s, err: %w", status, err) - waitTick(ctx, ticker) - err = s.pool.UpdateTxsStatus(ctx, hashes, status) - } -} - -func (s *Sequencer) incrementFailedCounter(ctx context.Context, ticker *time.Ticker, hashes []string) { - err := s.pool.IncrementFailedCounter(ctx, hashes) - for err != nil { - log.Errorf("failed to increment failed tx counter, err: %w", err) - waitTick(ctx, ticker) - err = s.pool.IncrementFailedCounter(ctx, hashes) - } -} - -func (s *Sequencer) isTxNonceLessThanAccountNonce(ctx context.Context, tx *state.ProcessTransactionResponse) (bool, error) { - fromAddr, txNonce, err := s.pool.GetTxFromAddressFromByHash(ctx, tx.Tx.Hash()) - if err != nil { - return false, fmt.Errorf("failed to get from addr, err: %w", err) - } - - lastL2BlockNumber, err := s.state.GetLastL2BlockNumber(ctx, nil) - if err != nil { - return false, fmt.Errorf("failed to get last l2 block number, err: %w", err) - } - - accNonce, err := s.state.GetNonce(ctx, fromAddr, lastL2BlockNumber, nil) - if err != nil { - return false, fmt.Errorf("failed to get nonce for the account, err: %w", err) - } - - return txNonce < accNonce, nil -} - -func (s *Sequencer) newSequence(ctx context.Context) (types.Sequence, error) { - var ( - dbTx pgx.Tx - err error - ) - if s.sequenceInProgress.StateRoot.String() == "" || s.sequenceInProgress.LocalExitRoot.String() == "" { - return types.Sequence{}, errors.New("state root and local exit root must have value to close batch") - } - dbTx, err = s.state.BeginStateTransaction(ctx) - if err != nil { - return types.Sequence{}, fmt.Errorf("failed to begin state transaction to close batch, err: %w", err) - } - - lastBatchNumber, err := s.state.GetLastBatchNumber(ctx, dbTx) - if err != nil { - return types.Sequence{}, fmt.Errorf("failed to get last batch number, err: %w", err) - } - err = s.closeBatch(ctx, lastBatchNumber, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - return types.Sequence{}, fmt.Errorf( - "failed to rollback dbTx when closing batch that gave err: %s. Rollback err: %s", - rollbackErr.Error(), err.Error(), - ) - } - return types.Sequence{}, err - } - // open next batch - gerHash, err := s.getLatestGer(ctx, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - return types.Sequence{}, fmt.Errorf( - "failed to rollback dbTx when getting last GER that gave err: %s. Rollback err: %s", - rollbackErr.Error(), err.Error(), - ) - } - return types.Sequence{}, err - } - - processingCtx, err := s.openBatch(ctx, gerHash, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - return types.Sequence{}, fmt.Errorf( - "failed to rollback dbTx when getting last batch num that gave err: %s. Rollback err: %s", - rollbackErr.Error(), err.Error(), - ) - } - return types.Sequence{}, err - } - if err := dbTx.Commit(ctx); err != nil { - return types.Sequence{}, err - } - return types.Sequence{ - GlobalExitRoot: processingCtx.GlobalExitRoot, - Timestamp: processingCtx.Timestamp.Unix(), - Txs: []ethTypes.Transaction{}, - }, nil -} - -func (s *Sequencer) closeSequence(ctx context.Context) error { - newSequence, err := s.newSequence(ctx) - if err != nil { - return fmt.Errorf("failed to create new sequence, err: %w", err) - } - s.sequenceInProgress = newSequence - return nil -} - -func (s *Sequencer) isSequenceProfitable(ctx context.Context) bool { - isProfitable, err := s.checker.IsSequenceProfitable(ctx, s.sequenceInProgress) - if err != nil { - log.Errorf("failed to check is sequence profitable, err: %w", err) - return false - } - - return isProfitable -} - -func (s *Sequencer) processTxs(ctx context.Context) (processTxResponse, error) { - dbTx, err := s.state.BeginStateTransaction(ctx) - if err != nil { - log.Errorf("failed to begin state transaction for processing tx, err: %w", err) - return processTxResponse{}, err - } - - lastBatchNumber, err := s.state.GetLastBatchNumber(ctx, dbTx) - if err != nil { - log.Errorf("failed to get last batch number, err: %w", err) - return processTxResponse{}, err - } - - processBatchResp, err := s.state.ProcessSequencerBatch(ctx, lastBatchNumber, s.sequenceInProgress.Txs, dbTx) - if err != nil { - if err == state.ErrBatchAlreadyClosed || err == state.ErrInvalidBatchNumber { - log.Warnf("unexpected state local vs DB: %w", err) - log.Info("reloading local sequence") - errLoadSeq := s.loadSequenceFromState(ctx) - if errLoadSeq != nil { - log.Errorf("error loading sequence from state: %w", errLoadSeq) - } - } - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - log.Errorf( - "failed to rollback dbTx when processing tx that gave err: %w. Rollback err: %v", - rollbackErr, err, - ) - return processTxResponse{}, err - } - log.Errorf("failed processing batch, err: %w", err) - return processTxResponse{}, err - } - - if err := dbTx.Commit(ctx); err != nil { - log.Errorf("failed to commit dbTx when processing tx, err: %w", err) - return processTxResponse{}, err - } - - s.sequenceInProgress.StateRoot = processBatchResp.NewStateRoot - s.sequenceInProgress.LocalExitRoot = processBatchResp.NewLocalExitRoot - - processedTxs, processedTxsHashes, unprocessedTxs, unprocessedTxsHashes := state.DetermineProcessedTransactions(processBatchResp.Responses) - - response := processTxResponse{ - processedTxs: processedTxs, - processedTxsHashes: processedTxsHashes, - unprocessedTxs: unprocessedTxs, - unprocessedTxsHashes: unprocessedTxsHashes, - isBatchProcessed: processBatchResp.IsBatchProcessed, - } - - return response, nil -} - -func (s *Sequencer) storeProcessedTransactions(ctx context.Context, processedTxs []*state.ProcessTransactionResponse) error { - dbTx, err := s.state.BeginStateTransaction(ctx) - if err != nil { - log.Errorf("failed to begin state transaction for StoreTransactions, err: %w", err) - return err - } - - lastBatchNumber, err := s.state.GetLastBatchNumber(ctx, dbTx) - if err != nil { - log.Errorf("failed to get last batch number, err: %w", err) - return err - } - - err = s.state.StoreTransactions(ctx, lastBatchNumber, processedTxs, dbTx) - if err != nil { - s.sequenceInProgress.Txs = s.sequenceInProgress.Txs[:len(s.sequenceInProgress.Txs)-len(processedTxs)] - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - log.Errorf( - "failed to rollback dbTx when StoreTransactions that gave err: %w. Rollback err: %w", - rollbackErr, err, - ) - return err - } - log.Errorf("failed to store transactions, err: %w", err) - if err == state.ErrOutOfOrderProcessedTx || err == state.ErrExistingTxGreaterThanProcessedTx { - err = s.loadSequenceFromState(ctx) - if err != nil { - log.Errorf("failed to load sequence from state, err: %w", err) - } - } - return err - } - - if err := dbTx.Commit(ctx); err != nil { - log.Errorf("failed to commit dbTx when StoreTransactions, err: %w", err) - return err - } - - return nil -} - -func (s *Sequencer) updateGerInBatch(ctx context.Context, lastGer *state.GlobalExitRoot) error { - log.Info("update GER without closing batch as no txs have been added yet") - - dbTx, err := s.state.BeginStateTransaction(ctx) - if err != nil { - log.Errorf("failed to begin state transaction for UpdateGERInOpenBatch tx, err: %w", err) - return err - } - - err = s.state.UpdateGERInOpenBatch(ctx, lastGer.GlobalExitRoot, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - log.Errorf( - "failed to rollback dbTx when UpdateGERInOpenBatch that gave err: %w. Rollback err: %w", - rollbackErr, err, - ) - return err - } - log.Errorf("failed to update ger in open batch, err: %w", err) - return err - } - - if err := dbTx.Commit(ctx); err != nil { - log.Errorf("failed to commit dbTx when processing UpdateGERInOpenBatch, err: %w", err.Error()) - return err - } - - return nil -} - -func (s *Sequencer) closeBatch(ctx context.Context, lastBatchNumber uint64, dbTx pgx.Tx) error { - receipt := state.ProcessingReceipt{ - BatchNumber: lastBatchNumber, - StateRoot: s.sequenceInProgress.StateRoot, - LocalExitRoot: s.sequenceInProgress.LocalExitRoot, - } - err := s.state.CloseBatch(ctx, receipt, dbTx) - if err != nil { - return fmt.Errorf("failed to close batch, err: %w", err) - } - - return nil -} - -func (s *Sequencer) getLatestGer(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) { - ger, err := s.state.GetLatestGlobalExitRoot(ctx, dbTx) - if err != nil && errors.Is(err, state.ErrNotFound) { - return state.ZeroHash, nil - } else if err != nil { - return common.Hash{}, fmt.Errorf("failed to get latest global exit root, err: %w", err) - } else { - return ger.GlobalExitRoot, nil - } -} - -func (s *Sequencer) openBatch(ctx context.Context, gerHash common.Hash, dbTx pgx.Tx) (state.ProcessingContext, error) { - lastBatchNum, err := s.state.GetLastBatchNumber(ctx, nil) - if err != nil { - return state.ProcessingContext{}, fmt.Errorf("failed to get last batch number, err: %w", err) - } - newBatchNum := lastBatchNum + 1 - processingCtx := state.ProcessingContext{ - BatchNumber: newBatchNum, - Coinbase: s.address, - Timestamp: time.Now(), - GlobalExitRoot: gerHash, - } - err = s.state.OpenBatch(ctx, processingCtx, dbTx) - if err != nil { - return state.ProcessingContext{}, fmt.Errorf("failed to open new batch, err: %w", err) - } - - return processingCtx, nil -} - -func (s *Sequencer) appendPendingTxs(ctx context.Context, isClaims bool, minGasPrice, getTxsLimit uint64, ticker *time.Ticker) uint64 { - pendTxs, err := s.pool.GetTxs(ctx, pool.TxStatusPending, isClaims, minGasPrice, getTxsLimit) - if err == pgpoolstorage.ErrNotFound || len(pendTxs) == 0 { - pendTxs, err = s.pool.GetTxs(ctx, pool.TxStatusFailed, isClaims, minGasPrice, getTxsLimit) - if err == pgpoolstorage.ErrNotFound || len(pendTxs) == 0 { - log.Info("there is no suitable pending or failed txs in the pool, waiting...") - waitTick(ctx, ticker) - return 0 - } - } else if err != nil { - log.Errorf("failed to get pending tx, err: %w", err) - return 0 - } - for i := 0; i < len(pendTxs); i++ { - s.sequenceInProgress.Txs = append(s.sequenceInProgress.Txs, pendTxs[i].Transaction) - } - - return uint64(len(pendTxs)) -} diff --git a/sequencer/broadcast/client.go b/sequencer/broadcast/client.go deleted file mode 100644 index e9e76ac3f6..0000000000 --- a/sequencer/broadcast/client.go +++ /dev/null @@ -1,30 +0,0 @@ -package broadcast - -import ( - "context" - "time" - - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -// NewClient creates a grpc client to communicates with the Broadcast server -func NewClient(ctx context.Context, serverAddress string) (pb.BroadcastServiceClient, *grpc.ClientConn, context.CancelFunc) { - opts := []grpc.DialOption{ - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithBlock(), - } - const maxWaitSeconds = 120 - ctx, cancel := context.WithTimeout(ctx, maxWaitSeconds*time.Second) - log.Infof("connecting to broadcast service: %v", serverAddress) - conn, err := grpc.DialContext(ctx, serverAddress, opts...) - if err != nil { - log.Fatalf("failed to connect to broadcast service: %v", err) - } - client := pb.NewBroadcastServiceClient(conn) - log.Info("connected to broadcast service") - - return client, conn, cancel -} diff --git a/sequencer/broadcast/config.go b/sequencer/broadcast/config.go deleted file mode 100644 index 8023fcfaee..0000000000 --- a/sequencer/broadcast/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package broadcast - -// ServerConfig represents the configuration of the broadcast server. -type ServerConfig struct { - Host string `mapstructure:"Host"` - Port int `mapstructure:"Port"` -} diff --git a/sequencer/broadcast/interfaces.go b/sequencer/broadcast/interfaces.go deleted file mode 100644 index 035eef3164..0000000000 --- a/sequencer/broadcast/interfaces.go +++ /dev/null @@ -1,19 +0,0 @@ -package broadcast - -import ( - "context" - - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - "github.com/jackc/pgx/v4" -) - -// Consumer interfaces required by the package. - -type stateInterface interface { - GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) - GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) - GetEncodedTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (encoded []string, err error) - GetForcedBatchByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.ForcedBatch, error) - GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*state.GlobalExitRoot, error) -} diff --git a/sequencer/broadcast/mocks/mock_state.go b/sequencer/broadcast/mocks/mock_state.go deleted file mode 100644 index e00f679a5a..0000000000 --- a/sequencer/broadcast/mocks/mock_state.go +++ /dev/null @@ -1,150 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - common "github.com/ethereum/go-ethereum/common" - - mock "github.com/stretchr/testify/mock" - - pgx "github.com/jackc/pgx/v4" - - state "github.com/0xPolygonHermez/zkevm-node/state" -) - -// StateMock is an autogenerated mock type for the stateInterface type -type StateMock struct { - mock.Mock -} - -// GetBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { - ret := _m.Called(ctx, batchNumber, dbTx) - - var r0 *state.Batch - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { - r0 = rf(ctx, batchNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*state.Batch) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetEncodedTransactionsByBatchNumber provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) GetEncodedTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]string, error) { - ret := _m.Called(ctx, batchNumber, dbTx) - - var r0 []string - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) []string); ok { - r0 = rf(ctx, batchNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetExitRootByGlobalExitRoot provides a mock function with given fields: ctx, ger, dbTx -func (_m *StateMock) GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*state.GlobalExitRoot, error) { - ret := _m.Called(ctx, ger, dbTx) - - var r0 *state.GlobalExitRoot - if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pgx.Tx) *state.GlobalExitRoot); ok { - r0 = rf(ctx, ger, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*state.GlobalExitRoot) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, common.Hash, pgx.Tx) error); ok { - r1 = rf(ctx, ger, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetForcedBatchByBatchNumber provides a mock function with given fields: ctx, batchNumber, dbTx -func (_m *StateMock) GetForcedBatchByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.ForcedBatch, error) { - ret := _m.Called(ctx, batchNumber, dbTx) - - var r0 *state.ForcedBatch - if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.ForcedBatch); ok { - r0 = rf(ctx, batchNumber, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*state.ForcedBatch) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetLastBatch provides a mock function with given fields: ctx, dbTx -func (_m *StateMock) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) { - ret := _m.Called(ctx, dbTx) - - var r0 *state.Batch - if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Batch); ok { - r0 = rf(ctx, dbTx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*state.Batch) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { - r1 = rf(ctx, dbTx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewStateMock interface { - mock.TestingT - Cleanup(func()) -} - -// NewStateMock creates a new instance of StateMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStateMock(t mockConstructorTestingTNewStateMock) *StateMock { - mock := &StateMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sequencer/broadcast/pb/broadcast.pb.go b/sequencer/broadcast/pb/broadcast.pb.go deleted file mode 100644 index 7431ddc7cc..0000000000 --- a/sequencer/broadcast/pb/broadcast.pb.go +++ /dev/null @@ -1,393 +0,0 @@ -//* -// Broadcast service. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.6 -// source: broadcast.proto - -package pb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Requests -type GetBatchRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BatchNumber uint64 `protobuf:"varint,1,opt,name=batch_number,json=batchNumber,proto3" json:"batch_number,omitempty"` -} - -func (x *GetBatchRequest) Reset() { - *x = GetBatchRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_broadcast_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetBatchRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetBatchRequest) ProtoMessage() {} - -func (x *GetBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_broadcast_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetBatchRequest.ProtoReflect.Descriptor instead. -func (*GetBatchRequest) Descriptor() ([]byte, []int) { - return file_broadcast_proto_rawDescGZIP(), []int{0} -} - -func (x *GetBatchRequest) GetBatchNumber() uint64 { - if x != nil { - return x.BatchNumber - } - return 0 -} - -// Responses -type GetBatchResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BatchNumber uint64 `protobuf:"varint,1,opt,name=batch_number,json=batchNumber,proto3" json:"batch_number,omitempty"` - GlobalExitRoot string `protobuf:"bytes,2,opt,name=global_exit_root,json=globalExitRoot,proto3" json:"global_exit_root,omitempty"` - LocalExitRoot string `protobuf:"bytes,3,opt,name=local_exit_root,json=localExitRoot,proto3" json:"local_exit_root,omitempty"` - StateRoot string `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty"` - MainnetExitRoot string `protobuf:"bytes,5,opt,name=mainnet_exit_root,json=mainnetExitRoot,proto3" json:"mainnet_exit_root,omitempty"` - RollupExitRoot string `protobuf:"bytes,6,opt,name=rollup_exit_root,json=rollupExitRoot,proto3" json:"rollup_exit_root,omitempty"` - Timestamp uint64 `protobuf:"varint,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Sequencer string `protobuf:"bytes,8,opt,name=sequencer,proto3" json:"sequencer,omitempty"` - ForcedBatchNumber uint64 `protobuf:"varint,9,opt,name=forced_batch_number,json=forcedBatchNumber,proto3" json:"forced_batch_number,omitempty"` - Transactions []*Transaction `protobuf:"bytes,10,rep,name=transactions,proto3" json:"transactions,omitempty"` -} - -func (x *GetBatchResponse) Reset() { - *x = GetBatchResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_broadcast_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetBatchResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetBatchResponse) ProtoMessage() {} - -func (x *GetBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_broadcast_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetBatchResponse.ProtoReflect.Descriptor instead. -func (*GetBatchResponse) Descriptor() ([]byte, []int) { - return file_broadcast_proto_rawDescGZIP(), []int{1} -} - -func (x *GetBatchResponse) GetBatchNumber() uint64 { - if x != nil { - return x.BatchNumber - } - return 0 -} - -func (x *GetBatchResponse) GetGlobalExitRoot() string { - if x != nil { - return x.GlobalExitRoot - } - return "" -} - -func (x *GetBatchResponse) GetLocalExitRoot() string { - if x != nil { - return x.LocalExitRoot - } - return "" -} - -func (x *GetBatchResponse) GetStateRoot() string { - if x != nil { - return x.StateRoot - } - return "" -} - -func (x *GetBatchResponse) GetMainnetExitRoot() string { - if x != nil { - return x.MainnetExitRoot - } - return "" -} - -func (x *GetBatchResponse) GetRollupExitRoot() string { - if x != nil { - return x.RollupExitRoot - } - return "" -} - -func (x *GetBatchResponse) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *GetBatchResponse) GetSequencer() string { - if x != nil { - return x.Sequencer - } - return "" -} - -func (x *GetBatchResponse) GetForcedBatchNumber() uint64 { - if x != nil { - return x.ForcedBatchNumber - } - return 0 -} - -func (x *GetBatchResponse) GetTransactions() []*Transaction { - if x != nil { - return x.Transactions - } - return nil -} - -// Common -type Transaction struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Encoded string `protobuf:"bytes,1,opt,name=encoded,proto3" json:"encoded,omitempty"` -} - -func (x *Transaction) Reset() { - *x = Transaction{} - if protoimpl.UnsafeEnabled { - mi := &file_broadcast_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Transaction) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Transaction) ProtoMessage() {} - -func (x *Transaction) ProtoReflect() protoreflect.Message { - mi := &file_broadcast_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Transaction.ProtoReflect.Descriptor instead. -func (*Transaction) Descriptor() ([]byte, []int) { - return file_broadcast_proto_rawDescGZIP(), []int{2} -} - -func (x *Transaction) GetEncoded() string { - if x != nil { - return x.Encoded - } - return "" -} - -var File_broadcast_proto protoreflect.FileDescriptor - -var file_broadcast_proto_rawDesc = []byte{ - 0x0a, 0x0f, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x0c, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x1a, - 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x0f, - 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0x22, 0xa7, 0x03, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, - 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x78, - 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, - 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x6d, - 0x61, 0x69, 0x6e, 0x6e, 0x65, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x61, 0x69, 0x6e, 0x6e, 0x65, 0x74, 0x45, - 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6c, 0x6c, 0x75, - 0x70, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x2e, 0x0a, - 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, - 0x65, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3d, 0x0a, - 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x27, 0x0a, 0x0b, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, - 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, - 0x63, 0x6f, 0x64, 0x65, 0x64, 0x32, 0xa5, 0x01, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, - 0x61, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x47, 0x65, - 0x74, 0x4c, 0x61, 0x73, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1e, 0x2e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x49, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, - 0x2e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, - 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, - 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, - 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, - 0x2f, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_broadcast_proto_rawDescOnce sync.Once - file_broadcast_proto_rawDescData = file_broadcast_proto_rawDesc -) - -func file_broadcast_proto_rawDescGZIP() []byte { - file_broadcast_proto_rawDescOnce.Do(func() { - file_broadcast_proto_rawDescData = protoimpl.X.CompressGZIP(file_broadcast_proto_rawDescData) - }) - return file_broadcast_proto_rawDescData -} - -var file_broadcast_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_broadcast_proto_goTypes = []interface{}{ - (*GetBatchRequest)(nil), // 0: broadcast.v1.GetBatchRequest - (*GetBatchResponse)(nil), // 1: broadcast.v1.GetBatchResponse - (*Transaction)(nil), // 2: broadcast.v1.Transaction - (*emptypb.Empty)(nil), // 3: google.protobuf.Empty -} -var file_broadcast_proto_depIdxs = []int32{ - 2, // 0: broadcast.v1.GetBatchResponse.transactions:type_name -> broadcast.v1.Transaction - 3, // 1: broadcast.v1.BroadcastService.GetLastBatch:input_type -> google.protobuf.Empty - 0, // 2: broadcast.v1.BroadcastService.GetBatch:input_type -> broadcast.v1.GetBatchRequest - 1, // 3: broadcast.v1.BroadcastService.GetLastBatch:output_type -> broadcast.v1.GetBatchResponse - 1, // 4: broadcast.v1.BroadcastService.GetBatch:output_type -> broadcast.v1.GetBatchResponse - 3, // [3:5] is the sub-list for method output_type - 1, // [1:3] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_broadcast_proto_init() } -func file_broadcast_proto_init() { - if File_broadcast_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_broadcast_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetBatchRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_broadcast_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetBatchResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_broadcast_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Transaction); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_broadcast_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_broadcast_proto_goTypes, - DependencyIndexes: file_broadcast_proto_depIdxs, - MessageInfos: file_broadcast_proto_msgTypes, - }.Build() - File_broadcast_proto = out.File - file_broadcast_proto_rawDesc = nil - file_broadcast_proto_goTypes = nil - file_broadcast_proto_depIdxs = nil -} diff --git a/sequencer/broadcast/pb/broadcast_grpc.pb.go b/sequencer/broadcast/pb/broadcast_grpc.pb.go deleted file mode 100644 index 1fcc04db48..0000000000 --- a/sequencer/broadcast/pb/broadcast_grpc.pb.go +++ /dev/null @@ -1,142 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.6 -// source: broadcast.proto - -package pb - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - emptypb "google.golang.org/protobuf/types/known/emptypb" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// BroadcastServiceClient is the client API for BroadcastService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type BroadcastServiceClient interface { - GetLastBatch(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetBatchResponse, error) - GetBatch(ctx context.Context, in *GetBatchRequest, opts ...grpc.CallOption) (*GetBatchResponse, error) -} - -type broadcastServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewBroadcastServiceClient(cc grpc.ClientConnInterface) BroadcastServiceClient { - return &broadcastServiceClient{cc} -} - -func (c *broadcastServiceClient) GetLastBatch(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetBatchResponse, error) { - out := new(GetBatchResponse) - err := c.cc.Invoke(ctx, "/broadcast.v1.BroadcastService/GetLastBatch", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *broadcastServiceClient) GetBatch(ctx context.Context, in *GetBatchRequest, opts ...grpc.CallOption) (*GetBatchResponse, error) { - out := new(GetBatchResponse) - err := c.cc.Invoke(ctx, "/broadcast.v1.BroadcastService/GetBatch", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// BroadcastServiceServer is the server API for BroadcastService service. -// All implementations must embed UnimplementedBroadcastServiceServer -// for forward compatibility -type BroadcastServiceServer interface { - GetLastBatch(context.Context, *emptypb.Empty) (*GetBatchResponse, error) - GetBatch(context.Context, *GetBatchRequest) (*GetBatchResponse, error) - mustEmbedUnimplementedBroadcastServiceServer() -} - -// UnimplementedBroadcastServiceServer must be embedded to have forward compatible implementations. -type UnimplementedBroadcastServiceServer struct { -} - -func (UnimplementedBroadcastServiceServer) GetLastBatch(context.Context, *emptypb.Empty) (*GetBatchResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetLastBatch not implemented") -} -func (UnimplementedBroadcastServiceServer) GetBatch(context.Context, *GetBatchRequest) (*GetBatchResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBatch not implemented") -} -func (UnimplementedBroadcastServiceServer) mustEmbedUnimplementedBroadcastServiceServer() {} - -// UnsafeBroadcastServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to BroadcastServiceServer will -// result in compilation errors. -type UnsafeBroadcastServiceServer interface { - mustEmbedUnimplementedBroadcastServiceServer() -} - -func RegisterBroadcastServiceServer(s grpc.ServiceRegistrar, srv BroadcastServiceServer) { - s.RegisterService(&BroadcastService_ServiceDesc, srv) -} - -func _BroadcastService_GetLastBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BroadcastServiceServer).GetLastBatch(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/broadcast.v1.BroadcastService/GetLastBatch", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BroadcastServiceServer).GetLastBatch(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BroadcastService_GetBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetBatchRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BroadcastServiceServer).GetBatch(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/broadcast.v1.BroadcastService/GetBatch", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BroadcastServiceServer).GetBatch(ctx, req.(*GetBatchRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// BroadcastService_ServiceDesc is the grpc.ServiceDesc for BroadcastService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var BroadcastService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "broadcast.v1.BroadcastService", - HandlerType: (*BroadcastServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetLastBatch", - Handler: _BroadcastService_GetLastBatch_Handler, - }, - { - MethodName: "GetBatch", - Handler: _BroadcastService_GetBatch_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "broadcast.proto", -} diff --git a/sequencer/broadcast/server.go b/sequencer/broadcast/server.go deleted file mode 100644 index c0e747f138..0000000000 --- a/sequencer/broadcast/server.go +++ /dev/null @@ -1,153 +0,0 @@ -package broadcast - -import ( - "context" - "fmt" - "net" - - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" - "github.com/0xPolygonHermez/zkevm-node/state" - "google.golang.org/grpc" - "google.golang.org/grpc/health/grpc_health_v1" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Server provides the functionality of the Broadcast service. -type Server struct { - cfg *ServerConfig - - srv *grpc.Server - pb.UnimplementedBroadcastServiceServer - state stateInterface -} - -// NewServer is the Broadcast server constructor. -func NewServer(cfg *ServerConfig, state stateInterface) *Server { - return &Server{ - cfg: cfg, - state: state, - } -} - -// SetState is the state setter. -func (s *Server) SetState(st stateInterface) { - s.state = st -} - -// Start sets up the server to process requests. -func (s *Server) Start() { - address := fmt.Sprintf("%s:%d", s.cfg.Host, s.cfg.Port) - lis, err := net.Listen("tcp", address) - if err != nil { - log.Fatalf("failed to listen: %v", err) - } - - s.srv = grpc.NewServer() - pb.RegisterBroadcastServiceServer(s.srv, s) - - healthService := newHealthChecker() - grpc_health_v1.RegisterHealthServer(s.srv, healthService) - - log.Infof("Server listening in %q", address) - if err := s.srv.Serve(lis); err != nil { - log.Fatalf("failed to serve: %v", err) - } -} - -// Stop stops the server. -func (s *Server) Stop() { - s.srv.Stop() -} - -// Implementation of pb.BroadcastServiceServer interface methods. - -// GetBatch returns a batch by batch number. -func (s *Server) GetBatch(ctx context.Context, in *pb.GetBatchRequest) (*pb.GetBatchResponse, error) { - batch, err := s.state.GetBatchByNumber(ctx, in.BatchNumber, nil) - if err != nil { - return nil, err - } - return s.genericGetBatch(ctx, batch) -} - -// GetLastBatch returns the last batch. -func (s *Server) GetLastBatch(ctx context.Context, empty *emptypb.Empty) (*pb.GetBatchResponse, error) { - batch, err := s.state.GetLastBatch(ctx, nil) - if err != nil { - return nil, err - } - return s.genericGetBatch(ctx, batch) -} - -func (s *Server) genericGetBatch(ctx context.Context, batch *state.Batch) (*pb.GetBatchResponse, error) { - txs, err := s.state.GetEncodedTransactionsByBatchNumber(ctx, batch.BatchNumber, nil) - if err != nil { - return nil, err - } - transactions := make([]*pb.Transaction, len(txs)) - for i, tx := range txs { - transactions[i] = &pb.Transaction{ - Encoded: tx, - } - } - - var forcedBatchNum uint64 - forcedBatch, err := s.state.GetForcedBatchByBatchNumber(ctx, batch.BatchNumber, nil) - if err == nil { - forcedBatchNum = forcedBatch.ForcedBatchNumber - } else if err != state.ErrNotFound { - return nil, err - } - - var mainnetExitRoot, rollupExitRoot string - ger, err := s.state.GetExitRootByGlobalExitRoot(ctx, batch.GlobalExitRoot, nil) - if err == nil { - mainnetExitRoot = ger.MainnetExitRoot.String() - rollupExitRoot = ger.RollupExitRoot.String() - } else if err != state.ErrNotFound { - return nil, err - } - - return &pb.GetBatchResponse{ - BatchNumber: batch.BatchNumber, - GlobalExitRoot: batch.GlobalExitRoot.String(), - Sequencer: batch.Coinbase.String(), - LocalExitRoot: batch.LocalExitRoot.String(), - StateRoot: batch.StateRoot.String(), - MainnetExitRoot: mainnetExitRoot, - RollupExitRoot: rollupExitRoot, - Timestamp: uint64(batch.Timestamp.Unix()), - Transactions: transactions, - ForcedBatchNumber: forcedBatchNum, - }, nil -} - -// HealthChecker will provide an implementation of the HealthCheck interface. -type healthChecker struct{} - -// NewHealthChecker returns a health checker according to standard package -// grpc.health.v1. -func newHealthChecker() *healthChecker { - return &healthChecker{} -} - -// HealthCheck interface implementation. - -// Check returns the current status of the server for unary gRPC health requests, -// for now if the server is up and able to respond we will always return SERVING. -func (s *healthChecker) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) { - log.Info("Serving the Check request for health check") - return &grpc_health_v1.HealthCheckResponse{ - Status: grpc_health_v1.HealthCheckResponse_SERVING, - }, nil -} - -// Watch returns the current status of the server for stream gRPC health requests, -// for now if the server is up and able to respond we will always return SERVING. -func (s *healthChecker) Watch(req *grpc_health_v1.HealthCheckRequest, server grpc_health_v1.Health_WatchServer) error { - log.Info("Serving the Watch request for health check") - return server.Send(&grpc_health_v1.HealthCheckResponse{ - Status: grpc_health_v1.HealthCheckResponse_SERVING, - }) -} diff --git a/sequencer/broadcast/server_test.go b/sequencer/broadcast/server_test.go deleted file mode 100644 index c9d02b3e4d..0000000000 --- a/sequencer/broadcast/server_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package broadcast_test - -import ( - "context" - "errors" - "fmt" - "os" - "path" - "runtime" - "testing" - "time" - - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/mocks" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/0xPolygonHermez/zkevm-node/test/testutils" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/protobuf/types/known/emptypb" -) - -const ( - host = "0.0.0.0" - port = 61091 -) - -var ( - address = fmt.Sprintf("%s:%d", host, port) - broadcastSrv *broadcast.Server - conn *grpc.ClientConn - cancel context.CancelFunc - err error - ctx = context.Background() -) - -func init() { - // Change dir to project root - // This is important because we have relative paths to files containing test vectors - _, filename, _, _ := runtime.Caller(0) - dir := path.Join(path.Dir(filename), "../../") - err := os.Chdir(dir) - if err != nil { - panic(err) - } -} - -func TestMain(m *testing.M) { - initialize() - defer teardown() - - os.Exit(m.Run()) -} - -func initialize() { - broadcastSrv = initBroadcastServer() - go broadcastSrv.Start() - - conn, cancel, err = initConn() - if err != nil { - panic(err) - } - - err = operations.WaitGRPCHealthy(address) - if err != nil { - panic(err) - } -} - -func teardown() { - cancel() - broadcastSrv.Stop() -} - -func initConn() (*grpc.ClientConn, context.CancelFunc, error) { - opts := []grpc.DialOption{ - grpc.WithTransportCredentials(insecure.NewCredentials()), - } - ctx, cancel := context.WithTimeout(ctx, 1*time.Second) - conn, err := grpc.DialContext(ctx, address, opts...) - return conn, cancel, err -} - -func initBroadcastServer() *broadcast.Server { - s := grpc.NewServer() - st := new(mocks.StateMock) - cfg := &broadcast.ServerConfig{ - Host: host, - Port: port, - } - - broadcastSrv = broadcast.NewServer(cfg, st) - pb.RegisterBroadcastServiceServer(s, broadcastSrv) - - return broadcastSrv -} - -func TestBroadcastServerGetBatch(t *testing.T) { - tcs := []struct { - description string - inputBatchNumber uint64 - expectedBatch *state.Batch - expectedForcedBatch *state.ForcedBatch - expectedEncodedTxs []string - expectedGER *state.GlobalExitRoot - expectedErr bool - expectedErrMsg string - }{ - { - description: "happy path", - inputBatchNumber: 14, - expectedBatch: &state.Batch{ - BatchNumber: 14, - GlobalExitRoot: common.HexToHash("a"), - Timestamp: time.Now(), - }, - expectedForcedBatch: &state.ForcedBatch{ - ForcedBatchNumber: 1, - }, - expectedEncodedTxs: []string{"tx1", "tx2", "tx3"}, - expectedGER: &state.GlobalExitRoot{ - MainnetExitRoot: common.HexToHash("b"), - RollupExitRoot: common.HexToHash("c"), - }, - }, - { - description: "query errors are returned", - inputBatchNumber: 14, - expectedErr: true, - expectedErrMsg: "query error", - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - st := new(mocks.StateMock) - var err error - if tc.expectedErr { - err = errors.New(tc.expectedErrMsg) - } - st.On("GetBatchByNumber", mock.AnythingOfType("*context.valueCtx"), tc.inputBatchNumber, nil).Return(tc.expectedBatch, err) - st.On("GetEncodedTransactionsByBatchNumber", mock.AnythingOfType("*context.valueCtx"), tc.inputBatchNumber, nil).Return(tc.expectedEncodedTxs, err) - st.On("GetForcedBatchByBatchNumber", mock.AnythingOfType("*context.valueCtx"), tc.inputBatchNumber, nil).Return(tc.expectedForcedBatch, err) - if tc.expectedBatch != nil { - st.On("GetExitRootByGlobalExitRoot", mock.AnythingOfType("*context.valueCtx"), tc.expectedBatch.GlobalExitRoot, nil).Return(tc.expectedGER, err) - } - broadcastSrv.SetState(st) - - client := pb.NewBroadcastServiceClient(conn) - actualBatch, err := client.GetBatch(ctx, &pb.GetBatchRequest{ - BatchNumber: tc.inputBatchNumber, - }) - require.NoError(t, testutils.CheckError(err, tc.expectedErr, fmt.Sprintf("rpc error: code = Unknown desc = %s", tc.expectedErrMsg))) - - if err == nil { - require.Equal(t, tc.expectedBatch.BatchNumber, actualBatch.BatchNumber) - require.Equal(t, tc.expectedBatch.GlobalExitRoot.String(), actualBatch.GlobalExitRoot) - require.Equal(t, uint64(tc.expectedBatch.Timestamp.Unix()), actualBatch.Timestamp) - for i, encoded := range tc.expectedEncodedTxs { - require.Equal(t, encoded, actualBatch.Transactions[i].Encoded) - } - require.Equal(t, tc.expectedGER.MainnetExitRoot.String(), actualBatch.MainnetExitRoot) - require.Equal(t, tc.expectedGER.RollupExitRoot.String(), actualBatch.RollupExitRoot) - - require.True(t, st.AssertExpectations(t)) - } - }) - } -} - -func TestBroadcastServerGetLastBatch(t *testing.T) { - tcs := []struct { - description string - expectedBatch *state.Batch - expectedForcedBatch *state.ForcedBatch - expectedEncodedTxs []string - expectedGER *state.GlobalExitRoot - expectedErr bool - expectedErrMsg string - }{ - { - description: "happy path", - expectedBatch: &state.Batch{ - BatchNumber: 14, - GlobalExitRoot: common.HexToHash("a"), - Timestamp: time.Now(), - }, - expectedForcedBatch: &state.ForcedBatch{ - ForcedBatchNumber: 1, - }, - expectedEncodedTxs: []string{"tx1", "tx2", "tx3"}, - expectedGER: &state.GlobalExitRoot{ - MainnetExitRoot: common.HexToHash("b"), - RollupExitRoot: common.HexToHash("c"), - }, - }, - { - description: "query errors are returned", - expectedErr: true, - expectedErrMsg: "query error", - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - st := new(mocks.StateMock) - var err error - if tc.expectedErr { - err = errors.New(tc.expectedErrMsg) - } - st.On("GetLastBatch", mock.AnythingOfType("*context.valueCtx"), nil).Return(tc.expectedBatch, err) - if tc.expectedBatch != nil { - st.On("GetEncodedTransactionsByBatchNumber", mock.AnythingOfType("*context.valueCtx"), tc.expectedBatch.BatchNumber, nil).Return(tc.expectedEncodedTxs, err) - st.On("GetForcedBatchByBatchNumber", mock.AnythingOfType("*context.valueCtx"), tc.expectedBatch.BatchNumber, nil).Return(tc.expectedForcedBatch, err) - st.On("GetExitRootByGlobalExitRoot", mock.AnythingOfType("*context.valueCtx"), tc.expectedBatch.GlobalExitRoot, nil).Return(tc.expectedGER, err) - } - - broadcastSrv.SetState(st) - - client := pb.NewBroadcastServiceClient(conn) - actualBatch, err := client.GetLastBatch(ctx, &emptypb.Empty{}) - require.NoError(t, testutils.CheckError(err, tc.expectedErr, fmt.Sprintf("rpc error: code = Unknown desc = %s", tc.expectedErrMsg))) - - if err == nil { - require.Equal(t, tc.expectedBatch.BatchNumber, actualBatch.BatchNumber) - require.Equal(t, tc.expectedBatch.GlobalExitRoot.String(), actualBatch.GlobalExitRoot) - require.Equal(t, uint64(tc.expectedBatch.Timestamp.Unix()), actualBatch.Timestamp) - for i, encoded := range tc.expectedEncodedTxs { - require.Equal(t, encoded, actualBatch.Transactions[i].Encoded) - } - require.Equal(t, tc.expectedGER.MainnetExitRoot.String(), actualBatch.MainnetExitRoot) - require.Equal(t, tc.expectedGER.RollupExitRoot.String(), actualBatch.RollupExitRoot) - - require.True(t, st.AssertExpectations(t)) - } - }) - } -} diff --git a/sequencer/closingchecker.go b/sequencer/closingchecker.go deleted file mode 100644 index 123eb1ffd8..0000000000 --- a/sequencer/closingchecker.go +++ /dev/null @@ -1,94 +0,0 @@ -package sequencer - -import ( - "context" - "time" - - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/state" -) - -// shouldCloseSequenceInProgress checks if sequence should be closed or not -// in case it's enough blocks since last GER update, long time since last batch and sequence is profitable -func (s *Sequencer) shouldCloseSequenceInProgress(ctx context.Context) bool { - // Check if sequence is full - if s.isSequenceTooBig { - log.Infof("current sequence should be closed because it has reached the maximum data size") - s.isSequenceTooBig = false - return true - } - if len(s.sequenceInProgress.Txs) == int(maxTxsPerBatch) { - log.Infof("current sequence should be closed because it has reached the maximum capacity (%d txs)", maxTxsPerBatch) - return true - } - // Check if there are any deposits or GER needs to be updated - if isThereAnyDeposits, err := s.shouldCloseDueToNewDeposits(ctx); err != nil || isThereAnyDeposits { - return err == nil - } - // Check if it has been too long since a previous batch was virtualized - if isBatchVirtualized, err := s.shouldCloseTooLongSinceLastVirtualized(ctx); err != nil || isBatchVirtualized { - return err == nil - } - - return false -} - -// shouldCloseDueToNewDeposits return true if there has been new deposits on L1 for more than WaitBlocksToUpdateGER -// and the sequence is profitable (if profitability check is enabled) -func (s *Sequencer) shouldCloseDueToNewDeposits(ctx context.Context) (bool, error) { - blockNum, mainnetExitRoot, err := s.state.GetBlockNumAndMainnetExitRootByGER(ctx, s.sequenceInProgress.GlobalExitRoot, nil) - if err != nil && err != state.ErrNotFound { - log.Errorf("failed to get mainnetExitRoot and blockNum by ger, err: %v", err) - return false, err - } - - lastGer, err := s.state.GetLatestGlobalExitRoot(ctx, nil) - if err != nil && err != state.ErrNotFound { - log.Errorf("failed to get latest global exit root, err: %v", err) - return false, err - } - - if lastGer != nil && lastGer.MainnetExitRoot != mainnetExitRoot { - latestBlockNumber, err := s.etherman.GetLatestBlockNumber(ctx) - if err != nil { - log.Errorf("failed to get latest batch number from ethereum, err: %v", err) - return false, err - } - if latestBlockNumber-blockNum > s.cfg.WaitBlocksToUpdateGER { - if len(s.sequenceInProgress.Txs) == 0 { - err := s.updateGerInBatch(ctx, lastGer) - if err != nil { - return false, err - } - } else { - isProfitable := s.isSequenceProfitable(ctx) - if isProfitable { - log.Infof("current sequence should be closed because blocks have been mined since last GER and tx is profitable") - return true, nil - } - } - } - } - return false, nil -} - -// shouldCloseTooLongSinceLastVirtualized returns true if last batch virtualization happened -// more than MaxTimeForBatchToBeOpen ago and there are transactions in the current sequence -func (s *Sequencer) shouldCloseTooLongSinceLastVirtualized(ctx context.Context) (bool, error) { - lastBatchNumber, err := s.state.GetLastBatchNumber(ctx, nil) - if err != nil { - log.Errorf("failed to get last batch number, err: %w", err) - return false, err - } - isPreviousBatchVirtualized, err := s.state.IsBatchVirtualized(ctx, lastBatchNumber-1, nil) - if err != nil { - log.Errorf("failed to get last virtual batch num, err: %w", err) - return false, err - } - if time.Unix(s.sequenceInProgress.Timestamp, 0).Add(s.cfg.MaxTimeForBatchToBeOpen.Duration).Before(time.Now()) && - isPreviousBatchVirtualized && len(s.sequenceInProgress.Txs) > 0 { - log.Info("current sequence should be closed because because there are enough time to close a batch, previous batch is virtualized and batch has txs") - return true, nil - } - return false, nil -} diff --git a/sequencer/closingsignalsmanager.go b/sequencer/closingsignalsmanager.go new file mode 100644 index 0000000000..84aae76b0a --- /dev/null +++ b/sequencer/closingsignalsmanager.go @@ -0,0 +1,106 @@ +package sequencer + +import ( + "context" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" +) + +type closingSignalsManager struct { + ctx context.Context + dbManager dbManagerInterface + closingSignalCh ClosingSignalCh + cfg FinalizerCfg + lastForcedBatchNumSent uint64 + etherman etherman +} + +func newClosingSignalsManager(ctx context.Context, dbManager dbManagerInterface, closingSignalCh ClosingSignalCh, cfg FinalizerCfg, etherman etherman) *closingSignalsManager { + return &closingSignalsManager{ctx: ctx, dbManager: dbManager, closingSignalCh: closingSignalCh, cfg: cfg, etherman: etherman} +} + +func (c *closingSignalsManager) Start() { + go c.checkForcedBatches() + go c.checkGERUpdate() +} + +func (c *closingSignalsManager) checkGERUpdate() { + lastBatch, err := c.dbManager.GetLastBatch(c.ctx) + for err != nil { + log.Errorf("error getting last batch: %v", err) + time.Sleep(time.Second) + lastBatch, err = c.dbManager.GetLastBatch(c.ctx) + } + lastGERSent := lastBatch.GlobalExitRoot + for { + time.Sleep(c.cfg.ClosingSignalsManagerWaitForCheckingGER.Duration) + + lastL1BlockNumber, err := c.etherman.GetLatestBlockNumber(c.ctx) + if err != nil { + log.Errorf("error getting latest L1 block number: %v", err) + continue + } + + maxBlockNumber := uint64(0) + if c.cfg.GERFinalityNumberOfBlocks <= lastL1BlockNumber { + maxBlockNumber = lastL1BlockNumber - c.cfg.GERFinalityNumberOfBlocks + } + + ger, _, err := c.dbManager.GetLatestGer(c.ctx, maxBlockNumber) + if err != nil { + log.Errorf("error checking GER update: %v", err) + continue + } + + if ger.GlobalExitRoot != lastGERSent { + log.Debugf("sending GER update signal (GER: %v)", ger.GlobalExitRoot) + c.closingSignalCh.GERCh <- ger.GlobalExitRoot + lastGERSent = ger.GlobalExitRoot + } + } +} + +func (c *closingSignalsManager) checkForcedBatches() { + for { + time.Sleep(c.cfg.ClosingSignalsManagerWaitForCheckingForcedBatches.Duration) + + if c.lastForcedBatchNumSent == 0 { + lastTrustedForcedBatchNum, err := c.dbManager.GetLastTrustedForcedBatchNumber(c.ctx, nil) + if err != nil { + log.Errorf("error getting last trusted forced batch number: %v", err) + continue + } + if lastTrustedForcedBatchNum > 0 { + c.lastForcedBatchNumSent = lastTrustedForcedBatchNum + } + } + // Take into account L1 finality + lastBlock, err := c.dbManager.GetLastBlock(c.ctx, nil) + if err != nil { + log.Errorf("failed to get latest eth block number, err: %v", err) + continue + } + + blockNumber := lastBlock.BlockNumber + + maxBlockNumber := uint64(0) + finalityNumberOfBlocks := c.cfg.ForcedBatchesFinalityNumberOfBlocks + + if finalityNumberOfBlocks <= blockNumber { + maxBlockNumber = blockNumber - finalityNumberOfBlocks + } + + forcedBatches, err := c.dbManager.GetForcedBatchesSince(c.ctx, c.lastForcedBatchNumSent, maxBlockNumber, nil) + if err != nil { + log.Errorf("error checking forced batches: %v", err) + continue + } + + for _, forcedBatch := range forcedBatches { + log.Debugf("sending forced batch signal (forced batch number: %v)", forcedBatch.ForcedBatchNumber) + c.closingSignalCh.ForcedBatchCh <- *forcedBatch + c.lastForcedBatchNumSent = forcedBatch.ForcedBatchNumber + } + } +} diff --git a/sequencer/closingsignalsmanager_test.go b/sequencer/closingsignalsmanager_test.go new file mode 100644 index 0000000000..bcdedaa448 --- /dev/null +++ b/sequencer/closingsignalsmanager_test.go @@ -0,0 +1,161 @@ +package sequencer + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/merkletree" + mtDBclientpb "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + executorclientpb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4/pgxpool" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +const numberOfForcesBatches = 10 + +var ( + localStateDb *pgxpool.Pool + localTestDbManager *dbManager + localCtx context.Context + localMtDBCancel, localExecutorCancel context.CancelFunc + localMtDBServiceClient mtDBclientpb.StateDBServiceClient + localMtDBClientConn, localExecutorClientConn *grpc.ClientConn + localState *state.State + localExecutorClient executorclientpb.ExecutorServiceClient + testGER = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + testAddr = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + testRawData = common.Hex2Bytes("0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e880801cee7e01dc62f69a12c3510c6d64de04ee6346d84b6a017f3e786c7d87f963e75d8cc91fa983cd6d9cf55fff80d73bd26cd333b0f098acc1e58edb1fd484ad731b") +) + +type mocks struct { + Etherman *EthermanMock +} + +func setupTest(t *testing.T) { + initOrResetDB() + + localCtx = context.Background() + + localStateDb, err = db.NewSQLDB(dbutils.NewStateConfigFromEnv()) + if err != nil { + panic(err) + } + + zkProverURI := testutils.GetEnv("ZKPROVER_URI", "localhost") + localMtDBServerConfig := merkletree.Config{URI: fmt.Sprintf("%s:50061", zkProverURI)} + localExecutorServerConfig := executor.Config{URI: fmt.Sprintf("%s:50071", zkProverURI)} + + localExecutorClient, localExecutorClientConn, localExecutorCancel = executor.NewExecutorClient(localCtx, localExecutorServerConfig) + s := localExecutorClientConn.GetState() + log.Infof("executorClientConn state: %s", s.String()) + + localMtDBServiceClient, localMtDBClientConn, localMtDBCancel = merkletree.NewMTDBServiceClient(localCtx, localMtDBServerConfig) + s = localMtDBClientConn.GetState() + log.Infof("localStateDbClientConn state: %s", s.String()) + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + panic(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + localStateTree := merkletree.NewStateTree(localMtDBServiceClient) + localState = state.NewState(stateCfg, state.NewPostgresStorage(localStateDb), localExecutorClient, localStateTree, eventLog) + + batchConstraints := batchConstraints{ + MaxTxsPerBatch: 150, + MaxBatchBytesSize: 129848, + MaxCumulativeGasUsed: 30000000, + MaxKeccakHashes: 468, + MaxPoseidonHashes: 279620, + MaxPoseidonPaddings: 149796, + MaxMemAligns: 262144, + MaxArithmetics: 262144, + MaxBinaries: 262144, + MaxSteps: 8388608, + } + + localTestDbManager = newDBManager(localCtx, dbManagerCfg, nil, localState, nil, closingSignalCh, txsStore, batchConstraints) + + // Set genesis batch + dbTx, err := localState.BeginStateTransaction(localCtx) + require.NoError(t, err) + _, err = localState.SetGenesis(localCtx, state.Block{}, state.Genesis{}, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(localCtx)) +} + +func cleanup(t *testing.T) { + localMtDBCancel() + localMtDBClientConn.Close() + localExecutorCancel() + localExecutorClientConn.Close() +} + +func prepareForcedBatches(t *testing.T) { + // Create block + const sql = `INSERT INTO state.forced_batch (forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, block_num) VALUES ($1, $2, $3, $4, $5, $6)` + + for x := 0; x < numberOfForcesBatches; x++ { + forcedBatchNum := int64(x) + _, err := localState.PostgresStorage.Exec(localCtx, sql, forcedBatchNum, testGER.String(), time.Now(), testRawData, testAddr.String(), 0) + assert.NoError(t, err) + } +} + +func TestClosingSignalsManager(t *testing.T) { + m := mocks{ + Etherman: NewEthermanMock(t), + } + + setupTest(t) + channels := ClosingSignalCh{ + ForcedBatchCh: make(chan state.ForcedBatch), + } + + prepareForcedBatches(t) + closingSignalsManager := newClosingSignalsManager(localCtx, localTestDbManager, channels, cfg, m.Etherman) + closingSignalsManager.Start() + + newCtx, cancelFunc := context.WithTimeout(localCtx, time.Second*3) + defer cancelFunc() + + var fb *state.ForcedBatch + + for { + select { + case <-newCtx.Done(): + log.Infof("received context done, Err: %s", newCtx.Err()) + return + // Forced batch ch + case fb := <-channels.ForcedBatchCh: + log.Debug("Forced batch received", "forced batch", fb) + } + + if fb != nil { + break + } + } + + require.NotEqual(t, (*state.ForcedBatch)(nil), fb) + require.Equal(t, nil, fb.BlockNumber) + require.Equal(t, int64(1), fb.ForcedBatchNumber) + require.Equal(t, testGER, fb.GlobalExitRoot) + require.Equal(t, testAddr, fb.Sequencer) + require.Equal(t, testRawData, fb.RawTxsData) + + cleanup(t) +} diff --git a/sequencer/config.go b/sequencer/config.go index 537c31ed50..b46f8cfcc9 100644 --- a/sequencer/config.go +++ b/sequencer/config.go @@ -1,81 +1,136 @@ package sequencer import ( - "fmt" - "math/big" - "github.com/0xPolygonHermez/zkevm-node/config/types" - base "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker" ) // Config represents the configuration of a sequencer type Config struct { - // WaitPeriodSendSequence is the time the sequencer waits until - // trying to send a sequence to L1 - WaitPeriodSendSequence types.Duration `mapstructure:"WaitPeriodSendSequence"` // WaitPeriodPoolIsEmpty is the time the sequencer waits until // trying to add new txs to the state WaitPeriodPoolIsEmpty types.Duration `mapstructure:"WaitPeriodPoolIsEmpty"` - // LastBatchVirtualizationTimeMaxWaitPeriod is time since sequences should be sent - LastBatchVirtualizationTimeMaxWaitPeriod types.Duration `mapstructure:"LastBatchVirtualizationTimeMaxWaitPeriod"` - - // WaitBlocksToUpdateGER is number of blocks for sequencer to wait - WaitBlocksToUpdateGER uint64 `mapstructure:"WaitBlocksToUpdateGER"` - - // MaxTimeForBatchToBeOpen is time after which new batch should be closed - MaxTimeForBatchToBeOpen types.Duration `mapstructure:"MaxTimeForBatchToBeOpen"` - // BlocksAmountForTxsToBeDeleted is blocks amount after which txs will be deleted from the pool BlocksAmountForTxsToBeDeleted uint64 `mapstructure:"BlocksAmountForTxsToBeDeleted"` // FrequencyToCheckTxsForDelete is frequency with which txs will be checked for deleting FrequencyToCheckTxsForDelete types.Duration `mapstructure:"FrequencyToCheckTxsForDelete"` + // MaxTxsPerBatch is the maximum amount of transactions in the batch + MaxTxsPerBatch uint64 `mapstructure:"MaxTxsPerBatch"` + + // MaxBatchBytesSize is the maximum batch size in bytes + // (subtracted bits of all types.Sequence fields excluding BatchL2Data from MaxTxSizeForL1) + MaxBatchBytesSize uint64 `mapstructure:"MaxBatchBytesSize"` + // MaxCumulativeGasUsed is max gas amount used by batch MaxCumulativeGasUsed uint64 `mapstructure:"MaxCumulativeGasUsed"` // MaxKeccakHashes is max keccak hashes used by batch - MaxKeccakHashes int32 `mapstructure:"MaxKeccakHashes"` + MaxKeccakHashes uint32 `mapstructure:"MaxKeccakHashes"` // MaxPoseidonHashes is max poseidon hashes batch can handle - MaxPoseidonHashes int32 `mapstructure:"MaxPoseidonHashes"` + MaxPoseidonHashes uint32 `mapstructure:"MaxPoseidonHashes"` // MaxPoseidonPaddings is max poseidon paddings batch can handle - MaxPoseidonPaddings int32 `mapstructure:"MaxPoseidonPaddings"` + MaxPoseidonPaddings uint32 `mapstructure:"MaxPoseidonPaddings"` // MaxMemAligns is max mem aligns batch can handle - MaxMemAligns int32 `mapstructure:"MaxMemAligns"` + MaxMemAligns uint32 `mapstructure:"MaxMemAligns"` // MaxArithmetics is max arithmetics batch can handle - MaxArithmetics int32 `mapstructure:"MaxArithmetics"` + MaxArithmetics uint32 `mapstructure:"MaxArithmetics"` // MaxBinaries is max binaries batch can handle - MaxBinaries int32 `mapstructure:"MaxBinaries"` + MaxBinaries uint32 `mapstructure:"MaxBinaries"` // MaxSteps is max steps batch can handle - MaxSteps int32 `mapstructure:"MaxSteps"` + MaxSteps uint32 `mapstructure:"MaxSteps"` + + // WeightBatchBytesSize is the cost weight for the BatchBytesSize batch resource + WeightBatchBytesSize int `mapstructure:"WeightBatchBytesSize"` + + // WeightCumulativeGasUsed is the cost weight for the CumulativeGasUsed batch resource + WeightCumulativeGasUsed int `mapstructure:"WeightCumulativeGasUsed"` + + // WeightKeccakHashes is the cost weight for the KeccakHashes batch resource + WeightKeccakHashes int `mapstructure:"WeightKeccakHashes"` + + // WeightPoseidonHashes is the cost weight for the PoseidonHashes batch resource + WeightPoseidonHashes int `mapstructure:"WeightPoseidonHashes"` + + // WeightPoseidonPaddings is the cost weight for the PoseidonPaddings batch resource + WeightPoseidonPaddings int `mapstructure:"WeightPoseidonPaddings"` + + // WeightMemAligns is the cost weight for the MemAligns batch resource + WeightMemAligns int `mapstructure:"WeightMemAligns"` + + // WeightArithmetics is the cost weight for the Arithmetics batch resource + WeightArithmetics int `mapstructure:"WeightArithmetics"` + + // WeightBinaries is the cost weight for the Binaries batch resource + WeightBinaries int `mapstructure:"WeightBinaries"` - // ProfitabilityChecker configuration - ProfitabilityChecker profitabilitychecker.Config `mapstructure:"ProfitabilityChecker"` + // WeightSteps is the cost weight for the Steps batch resource + WeightSteps int `mapstructure:"WeightSteps"` - // Maximum size, in gas size, a sequence can reach - MaxSequenceSize MaxSequenceSize `mapstructure:"MaxSequenceSize"` + // TxLifetimeCheckTimeout is the time the sequencer waits to check txs lifetime + TxLifetimeCheckTimeout types.Duration `mapstructure:"TxLifetimeCheckTimeout"` + + // MaxTxLifetime is the time a tx can be in the sequencer memory + MaxTxLifetime types.Duration `mapstructure:"MaxTxLifetime"` + + // Finalizer's specific config properties + Finalizer FinalizerCfg `mapstructure:"Finalizer"` + + // DBManager's specific config properties + DBManager DBManagerCfg `mapstructure:"DBManager"` + + // Worker's specific config properties + Worker WorkerCfg `mapstructure:"Worker"` } -// MaxSequenceSize is a wrapper type that parses token amount to big int -type MaxSequenceSize struct { - *big.Int `validate:"required"` +// FinalizerCfg contains the finalizer's configuration properties +type FinalizerCfg struct { + // GERDeadlineTimeout is the time the finalizer waits after receiving closing signal to update Global Exit Root + GERDeadlineTimeout types.Duration `mapstructure:"GERDeadlineTimeout"` + + // ForcedBatchDeadlineTimeout is the time the finalizer waits after receiving closing signal to process Forced Batches + ForcedBatchDeadlineTimeout types.Duration `mapstructure:"ForcedBatchDeadlineTimeout"` + + // SleepDuration is the time the finalizer sleeps between each iteration, if there are no transactions to be processed + SleepDuration types.Duration `mapstructure:"SleepDuration"` + + // ResourcePercentageToCloseBatch is the percentage window of the resource left out for the batch to be closed + ResourcePercentageToCloseBatch uint32 `mapstructure:"ResourcePercentageToCloseBatch"` + + // GERFinalityNumberOfBlocks is number of blocks to consider GER final + GERFinalityNumberOfBlocks uint64 `mapstructure:"GERFinalityNumberOfBlocks"` + + // ClosingSignalsManagerWaitForCheckingL1Timeout is used by the closing signals manager to wait for its operation + ClosingSignalsManagerWaitForCheckingL1Timeout types.Duration `mapstructure:"ClosingSignalsManagerWaitForCheckingL1Timeout"` + + // ClosingSignalsManagerWaitForCheckingGER is used by the closing signals manager to wait for its operation + ClosingSignalsManagerWaitForCheckingGER types.Duration `mapstructure:"ClosingSignalsManagerWaitForCheckingGER"` + + // ClosingSignalsManagerWaitForCheckingL1Timeout is used by the closing signals manager to wait for its operation + ClosingSignalsManagerWaitForCheckingForcedBatches types.Duration `mapstructure:"ClosingSignalsManagerWaitForCheckingForcedBatches"` + + // ForcedBatchesFinalityNumberOfBlocks is number of blocks to consider GER final + ForcedBatchesFinalityNumberOfBlocks uint64 `mapstructure:"ForcedBatchesFinalityNumberOfBlocks"` + + // TimestampResolution is the resolution of the timestamp used to close a batch + TimestampResolution types.Duration `mapstructure:"TimestampResolution"` } -// UnmarshalText unmarshal token amount from float string to big int -func (m *MaxSequenceSize) UnmarshalText(data []byte) error { - amount, ok := new(big.Int).SetString(string(data), base.Base10) - if !ok { - return fmt.Errorf("failed to unmarshal string to float") - } - m.Int = amount +// WorkerCfg contains the Worker's configuration properties +type WorkerCfg struct { + // ResourceCostMultiplier is the multiplier for the resource cost + ResourceCostMultiplier float64 `mapstructure:"ResourceCostMultiplier"` +} - return nil +// DBManagerCfg contains the DBManager's configuration properties +type DBManagerCfg struct { + PoolRetrievalInterval types.Duration `mapstructure:"PoolRetrievalInterval"` + L2ReorgRetrievalInterval types.Duration `mapstructure:"L2ReorgRetrievalInterval"` } diff --git a/sequencer/dbmanager.go b/sequencer/dbmanager.go new file mode 100644 index 0000000000..ce0c4ccb44 --- /dev/null +++ b/sequencer/dbmanager.go @@ -0,0 +1,576 @@ +package sequencer + +import ( + "context" + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +// Pool Loader and DB Updater +type dbManager struct { + cfg DBManagerCfg + txPool txPool + state stateInterface + worker workerInterface + txsStore TxsStore + l2ReorgCh chan L2ReorgEvent + ctx context.Context + batchConstraints batchConstraints + numberOfReorgs uint64 +} + +func (d *dbManager) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { + return d.state.GetBatchByNumber(ctx, batchNumber, dbTx) +} + +// ClosingBatchParameters contains the necessary parameters to close a batch +type ClosingBatchParameters struct { + BatchNumber uint64 + StateRoot common.Hash + LocalExitRoot common.Hash + AccInputHash common.Hash + Txs []types.Transaction + BatchResources state.BatchResources + ClosingReason state.ClosingReason +} + +func newDBManager(ctx context.Context, config DBManagerCfg, txPool txPool, state stateInterface, worker *Worker, closingSignalCh ClosingSignalCh, txsStore TxsStore, batchConstraints batchConstraints) *dbManager { + numberOfReorgs, err := state.CountReorgs(ctx, nil) + if err != nil { + log.Error("failed to get number of reorgs: %v", err) + } + + return &dbManager{ctx: ctx, cfg: config, txPool: txPool, state: state, worker: worker, txsStore: txsStore, l2ReorgCh: closingSignalCh.L2ReorgCh, batchConstraints: batchConstraints, numberOfReorgs: numberOfReorgs} +} + +// Start stars the dbManager routines +func (d *dbManager) Start() { + go d.loadFromPool() + go func() { + for { + time.Sleep(d.cfg.L2ReorgRetrievalInterval.Duration) + d.checkIfReorg() + } + }() + go d.storeProcessedTxAndDeleteFromPool() +} + +// GetLastBatchNumber get the latest batch number from state +func (d *dbManager) GetLastBatchNumber(ctx context.Context) (uint64, error) { + return d.state.GetLastBatchNumber(ctx, nil) +} + +// OpenBatch opens a new batch to star processing transactions +func (d *dbManager) OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error { + return d.state.OpenBatch(ctx, processingContext, dbTx) +} + +// CreateFirstBatch is using during genesis +func (d *dbManager) CreateFirstBatch(ctx context.Context, sequencerAddress common.Address) state.ProcessingContext { + processingCtx := state.ProcessingContext{ + BatchNumber: 1, + Coinbase: sequencerAddress, + Timestamp: time.Now(), + GlobalExitRoot: state.ZeroHash, + } + dbTx, err := d.state.BeginStateTransaction(ctx) + if err != nil { + log.Errorf("failed to begin state transaction for opening a batch, err: %v", err) + return processingCtx + } + err = d.state.OpenBatch(ctx, processingCtx, dbTx) + if err != nil { + if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { + log.Errorf( + "failed to rollback dbTx when opening batch that gave err: %v. Rollback err: %v", + rollbackErr, err, + ) + } + log.Errorf("failed to open a batch, err: %v", err) + return processingCtx + } + if err := dbTx.Commit(ctx); err != nil { + log.Errorf("failed to commit dbTx when opening batch, err: %v", err) + return processingCtx + } + return processingCtx +} + +// checkIfReorg checks if a reorg has happened +func (d *dbManager) checkIfReorg() { + numberOfReorgs, err := d.state.CountReorgs(d.ctx, nil) + if err != nil { + log.Error("failed to get number of reorgs: %v", err) + } + + if numberOfReorgs != d.numberOfReorgs { + log.Warnf("New L2 reorg detected") + d.l2ReorgCh <- L2ReorgEvent{} + } +} + +// loadFromPool keeps loading transactions from the pool +func (d *dbManager) loadFromPool() { + for { + time.Sleep(d.cfg.PoolRetrievalInterval.Duration) + + poolTransactions, err := d.txPool.GetNonWIPPendingTxs(d.ctx, 0) + if err != nil && err != pool.ErrNotFound { + log.Errorf("load tx from pool: %v", err) + } + + for _, tx := range poolTransactions { + err := d.addTxToWorker(tx) + if err != nil { + log.Errorf("error adding transaction to worker: %v", err) + } + } + } +} + +func (d *dbManager) addTxToWorker(tx pool.Transaction) error { + txTracker, err := d.worker.NewTxTracker(tx.Transaction, tx.ZKCounters, tx.IP) + if err != nil { + return err + } + dropReason, isWIP := d.worker.AddTxTracker(d.ctx, txTracker) + if dropReason != nil { + failedReason := dropReason.Error() + return d.txPool.UpdateTxStatus(d.ctx, txTracker.Hash, pool.TxStatusFailed, false, &failedReason) + } else { + if isWIP { + return d.txPool.UpdateTxWIPStatus(d.ctx, tx.Hash(), true) + } + } + + return nil +} + +// BeginStateTransaction starts a db transaction in the state +func (d *dbManager) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + return d.state.BeginStateTransaction(ctx) +} + +// StoreProcessedTransaction stores a transaction in the state +func (d *dbManager) StoreProcessedTransaction(ctx context.Context, batchNumber uint64, processedTx *state.ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error { + return d.state.StoreTransaction(ctx, batchNumber, processedTx, coinbase, timestamp, dbTx) +} + +// DeleteTransactionFromPool deletes a transaction from the pool +func (d *dbManager) DeleteTransactionFromPool(ctx context.Context, txHash common.Hash) error { + return d.txPool.DeleteTransactionByHash(ctx, txHash) +} + +// storeProcessedTxAndDeleteFromPool stores a tx into the state and changes it status in the pool +func (d *dbManager) storeProcessedTxAndDeleteFromPool() { + for { + txToStore := <-d.txsStore.Ch + d.checkIfReorg() + + // Flush the state db + err := d.state.FlushMerkleTree(d.ctx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool. Error flushing state db: %v", err) + } + + log.Debugf("Storing tx %v", txToStore.txResponse.TxHash) + dbTx, err := d.BeginStateTransaction(d.ctx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + + err = d.StoreProcessedTransaction(d.ctx, txToStore.batchNumber, txToStore.txResponse, txToStore.coinbase, txToStore.timestamp, dbTx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + + // Update batch l2 data + batch, err := d.state.GetBatchByNumber(d.ctx, txToStore.batchNumber, dbTx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + + txData, err := state.EncodeTransaction(txToStore.txResponse.Tx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + batch.BatchL2Data = append(batch.BatchL2Data, txData...) + + if !txToStore.isForcedBatch { + err = d.state.UpdateBatchL2Data(d.ctx, txToStore.batchNumber, batch.BatchL2Data, dbTx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + } + + err = dbTx.Commit(d.ctx) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool error committing : %v", err) + } + + // Change Tx status to selected + err = d.txPool.UpdateTxStatus(d.ctx, txToStore.txResponse.TxHash, pool.TxStatusSelected, false, nil) + if err != nil { + log.Fatalf("StoreProcessedTxAndDeleteFromPool: %v", err) + } + + log.Infof("StoreProcessedTxAndDeleteFromPool: successfully stored tx: %v for batch: %v", txToStore.txResponse.TxHash.String(), txToStore.batchNumber) + d.txsStore.Wg.Done() + } +} + +// GetWIPBatch returns ready WIP batch +func (d *dbManager) GetWIPBatch(ctx context.Context) (*WipBatch, error) { + const two = 2 + var lastBatch, previousLastBatch *state.Batch + dbTx, err := d.BeginStateTransaction(ctx) + if err != nil { + return nil, err + } + defer func() { + err := dbTx.Commit(ctx) + if err != nil { + log.Errorf("failed to commit GetWIPBatch: %v", err) + } + }() + + lastBatches, err := d.state.GetLastNBatches(ctx, two, dbTx) + if err != nil { + return nil, err + } + + lastBatch = lastBatches[0] + if len(lastBatches) > 1 { + previousLastBatch = lastBatches[1] + } + + lastBatchTxs, _, err := state.DecodeTxs(lastBatch.BatchL2Data) + if err != nil { + return nil, err + } + lastBatch.Transactions = lastBatchTxs + + var prevLastBatchTxs []types.Transaction + if previousLastBatch != nil { + prevLastBatchTxs, _, err = state.DecodeTxs(previousLastBatch.BatchL2Data) + if err != nil { + return nil, err + } + } + + var lastStateRoot common.Hash + // If the last two batches have no txs, the stateRoot can not be retrieved from the l2block because there is no tx. + // In this case, the stateRoot must be gotten from the previousLastBatch + if len(lastBatchTxs) == 0 && previousLastBatch != nil && len(prevLastBatchTxs) == 0 { + lastStateRoot = previousLastBatch.StateRoot + } else { + lastStateRoot, err = d.state.GetLastStateRoot(ctx, dbTx) + if err != nil { + return nil, err + } + } + + wipBatch := &WipBatch{ + batchNumber: lastBatch.BatchNumber, + coinbase: lastBatch.Coinbase, + localExitRoot: lastBatch.LocalExitRoot, + timestamp: lastBatch.Timestamp, + globalExitRoot: lastBatch.GlobalExitRoot, + countOfTxs: len(lastBatch.Transactions), + } + + // Init counters to MAX values + var totalBytes uint64 = d.batchConstraints.MaxBatchBytesSize + var batchZkCounters state.ZKCounters = state.ZKCounters{ + CumulativeGasUsed: d.batchConstraints.MaxCumulativeGasUsed, + UsedKeccakHashes: d.batchConstraints.MaxKeccakHashes, + UsedPoseidonHashes: d.batchConstraints.MaxPoseidonHashes, + UsedPoseidonPaddings: d.batchConstraints.MaxPoseidonPaddings, + UsedMemAligns: d.batchConstraints.MaxMemAligns, + UsedArithmetics: d.batchConstraints.MaxArithmetics, + UsedBinaries: d.batchConstraints.MaxBinaries, + UsedSteps: d.batchConstraints.MaxSteps, + } + + isClosed, err := d.IsBatchClosed(ctx, lastBatch.BatchNumber) + if err != nil { + return nil, err + } + + if isClosed { + wipBatch.batchNumber = lastBatch.BatchNumber + 1 + wipBatch.stateRoot = lastBatch.StateRoot + wipBatch.initialStateRoot = lastBatch.StateRoot + + processingContext := &state.ProcessingContext{ + BatchNumber: wipBatch.batchNumber, + Coinbase: wipBatch.coinbase, + Timestamp: wipBatch.timestamp, + GlobalExitRoot: wipBatch.globalExitRoot, + } + err = d.state.OpenBatch(ctx, *processingContext, dbTx) + if err != nil { + if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { + log.Errorf( + "failed to rollback dbTx when opening batch that gave err: %v. Rollback err: %v", + rollbackErr, err, + ) + } + log.Errorf("failed to open a batch, err: %v", err) + return nil, err + } + if err := dbTx.Commit(ctx); err != nil { + log.Errorf("failed to commit dbTx when opening batch, err: %v", err) + return nil, err + } + } else { + wipBatch.stateRoot = lastStateRoot + wipBatch.initialStateRoot = previousLastBatch.StateRoot + batchL2DataLen := len(lastBatch.BatchL2Data) + + if batchL2DataLen > 0 { + wipBatch.countOfTxs = len(lastBatch.Transactions) + batchToExecute := *lastBatch + batchToExecute.BatchNumber = wipBatch.batchNumber + batchResponse, err := d.state.ExecuteBatch(ctx, batchToExecute, false, dbTx) + if err != nil { + return nil, err + } + + zkCounters := &state.ZKCounters{ + CumulativeGasUsed: batchResponse.GetCumulativeGasUsed(), + UsedKeccakHashes: batchResponse.CntKeccakHashes, + UsedPoseidonHashes: batchResponse.CntPoseidonHashes, + UsedPoseidonPaddings: batchResponse.CntPoseidonPaddings, + UsedMemAligns: batchResponse.CntMemAligns, + UsedArithmetics: batchResponse.CntArithmetics, + UsedBinaries: batchResponse.CntBinaries, + UsedSteps: batchResponse.CntSteps, + } + + err = batchZkCounters.Sub(*zkCounters) + if err != nil { + return nil, err + } + + totalBytes -= uint64(batchL2DataLen) + } else { + wipBatch.countOfTxs = 0 + } + } + + wipBatch.remainingResources = state.BatchResources{ZKCounters: batchZkCounters, Bytes: totalBytes} + return wipBatch, nil +} + +// GetLastClosedBatch gets the latest closed batch from state +func (d *dbManager) GetLastClosedBatch(ctx context.Context) (*state.Batch, error) { + return d.state.GetLastClosedBatch(ctx, nil) +} + +// GetLastBatch gets the latest batch from state +func (d *dbManager) GetLastBatch(ctx context.Context) (*state.Batch, error) { + batch, err := d.state.GetLastBatch(d.ctx, nil) + if err != nil { + return nil, err + } + return batch, nil +} + +// IsBatchClosed checks if a batch is closed +func (d *dbManager) IsBatchClosed(ctx context.Context, batchNum uint64) (bool, error) { + return d.state.IsBatchClosed(ctx, batchNum, nil) +} + +// GetLastNBatches gets the latest N batches from state +func (d *dbManager) GetLastNBatches(ctx context.Context, numBatches uint) ([]*state.Batch, error) { + return d.state.GetLastNBatches(ctx, numBatches, nil) +} + +// GetLatestGer gets the latest global exit root +func (d *dbManager) GetLatestGer(ctx context.Context, gerFinalityNumberOfBlocks uint64) (state.GlobalExitRoot, time.Time, error) { + return d.state.GetLatestGer(ctx, gerFinalityNumberOfBlocks) +} + +// CloseBatch closes a batch in the state +func (d *dbManager) CloseBatch(ctx context.Context, params ClosingBatchParameters) error { + processingReceipt := state.ProcessingReceipt{ + BatchNumber: params.BatchNumber, + StateRoot: params.StateRoot, + LocalExitRoot: params.LocalExitRoot, + AccInputHash: params.AccInputHash, + BatchResources: params.BatchResources, + ClosingReason: params.ClosingReason, + } + + batchL2Data, err := state.EncodeTransactions(params.Txs) + if err != nil { + return err + } + + processingReceipt.BatchL2Data = batchL2Data + + dbTx, err := d.BeginStateTransaction(ctx) + if err != nil { + return err + } + + err = d.state.CloseBatch(ctx, processingReceipt, dbTx) + if err != nil { + err2 := dbTx.Rollback(ctx) + if err2 != nil { + log.Errorf("CloseBatch error rolling back: %v", err2) + } + return err + } else { + err := dbTx.Commit(ctx) + if err != nil { + log.Errorf("CloseBatch error committing: %v", err) + return err + } + } + + return nil +} + +// ProcessForcedBatch process a forced batch +func (d *dbManager) ProcessForcedBatch(ForcedBatchNumber uint64, request state.ProcessRequest) (*state.ProcessBatchResponse, error) { + // Open Batch + processingCtx := state.ProcessingContext{ + BatchNumber: request.BatchNumber, + Coinbase: request.Coinbase, + Timestamp: request.Timestamp, + GlobalExitRoot: request.GlobalExitRoot, + ForcedBatchNum: &ForcedBatchNumber, + } + dbTx, err := d.state.BeginStateTransaction(d.ctx) + if err != nil { + log.Errorf("failed to begin state transaction for opening a forced batch, err: %v", err) + return nil, err + } + + err = d.state.OpenBatch(d.ctx, processingCtx, dbTx) + if err != nil { + if rollbackErr := dbTx.Rollback(d.ctx); rollbackErr != nil { + log.Errorf( + "failed to rollback dbTx when opening a forced batch that gave err: %v. Rollback err: %v", + rollbackErr, err, + ) + } + log.Errorf("failed to open a batch, err: %v", err) + return nil, err + } + + // Fetch Forced Batch + forcedBatch, err := d.state.GetForcedBatch(d.ctx, ForcedBatchNumber, dbTx) + if err != nil { + if rollbackErr := dbTx.Rollback(d.ctx); rollbackErr != nil { + log.Errorf( + "failed to rollback dbTx when getting forced batch err: %v. Rollback err: %v", + rollbackErr, err, + ) + } + log.Errorf("failed to get a forced batch, err: %v", err) + return nil, err + } + + // Process Batch + processBatchResponse, err := d.state.ProcessSequencerBatch(d.ctx, request.BatchNumber, forcedBatch.RawTxsData, request.Caller, dbTx) + if err != nil { + log.Errorf("failed to process a forced batch, err: %v", err) + return nil, err + } + + // Close Batch + txsBytes := uint64(0) + for _, resp := range processBatchResponse.Responses { + if !resp.ChangesStateRoot { + continue + } + txsBytes += resp.Tx.Size() + } + processingReceipt := state.ProcessingReceipt{ + BatchNumber: request.BatchNumber, + StateRoot: processBatchResponse.NewStateRoot, + LocalExitRoot: processBatchResponse.NewLocalExitRoot, + AccInputHash: processBatchResponse.NewAccInputHash, + BatchL2Data: forcedBatch.RawTxsData, + BatchResources: state.BatchResources{ + ZKCounters: processBatchResponse.UsedZkCounters, + Bytes: txsBytes, + }, + ClosingReason: state.ForcedBatchClosingReason, + } + + isClosed := false + tryToCloseAndCommit := true + for tryToCloseAndCommit { + if !isClosed { + closingErr := d.state.CloseBatch(d.ctx, processingReceipt, dbTx) + tryToCloseAndCommit = closingErr != nil + if tryToCloseAndCommit { + continue + } + isClosed = true + } + + if err := dbTx.Commit(d.ctx); err != nil { + log.Errorf("failed to commit dbTx when processing a forced batch, err: %v", err) + } + tryToCloseAndCommit = err != nil + } + + return processBatchResponse, nil +} + +// GetForcedBatchesSince gets L1 forced batches since timestamp +func (d *dbManager) GetForcedBatchesSince(ctx context.Context, forcedBatchNumber, maxBlockNumber uint64, dbTx pgx.Tx) ([]*state.ForcedBatch, error) { + return d.state.GetForcedBatchesSince(ctx, forcedBatchNumber, maxBlockNumber, dbTx) +} + +// GetLastL2BlockHeader gets the last l2 block number +func (d *dbManager) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) { + return d.state.GetLastL2BlockHeader(ctx, dbTx) +} + +func (d *dbManager) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) { + return d.state.GetLastBlock(ctx, dbTx) +} + +func (d *dbManager) GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + return d.state.GetLastTrustedForcedBatchNumber(ctx, dbTx) +} + +func (d *dbManager) GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + return d.state.GetBalanceByStateRoot(ctx, address, root) +} + +func (d *dbManager) GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64) (txs []types.Transaction, err error) { + return d.state.GetTransactionsByBatchNumber(ctx, batchNumber, nil) +} + +func (d *dbManager) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus, isWIP bool, failedReason *string) error { + return d.txPool.UpdateTxStatus(ctx, hash, newStatus, isWIP, failedReason) +} + +// GetLatestVirtualBatchTimestamp gets last virtual batch timestamp +func (d *dbManager) GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { + return d.state.GetLatestVirtualBatchTimestamp(ctx, dbTx) +} + +// CountReorgs returns the number of reorgs +func (d *dbManager) CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + return d.state.CountReorgs(ctx, dbTx) +} + +// FlushMerkleTree persists updates in the Merkle tree +func (d *dbManager) FlushMerkleTree(ctx context.Context) error { + return d.state.FlushMerkleTree(ctx) +} diff --git a/sequencer/dbmanager_test.go b/sequencer/dbmanager_test.go new file mode 100644 index 0000000000..762721240c --- /dev/null +++ b/sequencer/dbmanager_test.go @@ -0,0 +1,176 @@ +package sequencer + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/merkletree" + mtDBclientpb "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" + "github.com/0xPolygonHermez/zkevm-node/state" + executorclientpb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4/pgxpool" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +var ( + mtDBCancel context.CancelFunc + ctx context.Context + testState *state.State + stateTree *merkletree.StateTree + stateDb *pgxpool.Pool + err error + stateDBCfg = dbutils.NewStateConfigFromEnv() + stateCfg = state.Config{ + MaxCumulativeGasUsed: 800000, + ChainID: 1000, + } + dbManagerCfg = DBManagerCfg{PoolRetrievalInterval: types.NewDuration(500 * time.Millisecond)} + executorClient executorclientpb.ExecutorServiceClient + mtDBServiceClient mtDBclientpb.StateDBServiceClient + mtDBClientConn *grpc.ClientConn + testDbManager *dbManager +) + +func setupDBManager() { + initOrResetDB() + ctx = context.Background() + + stateDb, err = db.NewSQLDB(stateDBCfg) + if err != nil { + panic(err) + } + + zkProverURI := testutils.GetEnv("ZKPROVER_URI", "localhost") + mtDBServerConfig := merkletree.Config{URI: fmt.Sprintf("%s:50061", zkProverURI)} + + mtDBServiceClient, mtDBClientConn, mtDBCancel = merkletree.NewMTDBServiceClient(ctx, mtDBServerConfig) + s := mtDBClientConn.GetState() + log.Infof("stateDbClientConn state: %s", s.String()) + + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + panic(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + stateTree = merkletree.NewStateTree(mtDBServiceClient) + testState = state.NewState(stateCfg, state.NewPostgresStorage(stateDb), executorClient, stateTree, eventLog) + + // DBManager + closingSignalCh := ClosingSignalCh{ + ForcedBatchCh: make(chan state.ForcedBatch), + GERCh: make(chan common.Hash), + L2ReorgCh: make(chan L2ReorgEvent), + } + + txsStore := TxsStore{ + Ch: make(chan *txToStore), + Wg: new(sync.WaitGroup), + } + + batchConstraints := batchConstraints{ + MaxTxsPerBatch: 150, + MaxBatchBytesSize: 129848, + MaxCumulativeGasUsed: 30000000, + MaxKeccakHashes: 468, + MaxPoseidonHashes: 279620, + MaxPoseidonPaddings: 149796, + MaxMemAligns: 262144, + MaxArithmetics: 262144, + MaxBinaries: 262144, + MaxSteps: 8388608, + } + + testDbManager = newDBManager(ctx, dbManagerCfg, nil, testState, nil, closingSignalCh, txsStore, batchConstraints) +} + +func initOrResetDB() { + if err := dbutils.InitOrResetState(stateDBCfg); err != nil { + panic(err) + } +} + +func cleanupDBManager() { + mtDBCancel() + mtDBClientConn.Close() +} + +func TestOpenBatch(t *testing.T) { + setupDBManager() + defer stateDb.Close() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + _, err = testState.SetGenesis(ctx, state.Block{}, state.Genesis{}, dbTx) + require.NoError(t, err) + + processingContext := state.ProcessingContext{ + BatchNumber: 1, + Coinbase: common.Address{}, + Timestamp: time.Now().UTC(), + GlobalExitRoot: common.Hash{}, + } + + err = testDbManager.OpenBatch(ctx, processingContext, dbTx) + require.NoError(t, err) + err = dbTx.Commit(ctx) + require.NoError(t, err) + cleanupDBManager() +} + +func TestGetLastBatchNumber(t *testing.T) { + setupDBManager() + defer stateDb.Close() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + _, err = testState.SetGenesis(ctx, state.Block{}, state.Genesis{}, dbTx) + require.NoError(t, err) + + processingContext := state.ProcessingContext{ + BatchNumber: 1, + Coinbase: common.Address{}, + Timestamp: time.Now().UTC(), + GlobalExitRoot: common.Hash{}, + } + + err = testDbManager.OpenBatch(ctx, processingContext, dbTx) + require.NoError(t, err) + err = dbTx.Commit(ctx) + require.NoError(t, err) + + lastBatchNum, err := testDbManager.GetLastBatchNumber(ctx) + require.NoError(t, err) + require.Equal(t, uint64(1), lastBatchNum) + cleanupDBManager() +} + +func TestCreateFirstBatch(t *testing.T) { + setupDBManager() + defer stateDb.Close() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + _, err = testState.SetGenesis(ctx, state.Block{}, state.Genesis{}, dbTx) + require.NoError(t, err) + err = dbTx.Commit(ctx) + require.NoError(t, err) + + processingContext := testDbManager.CreateFirstBatch(ctx, common.Address{}) + require.Equal(t, uint64(1), processingContext.BatchNumber) + cleanupDBManager() +} diff --git a/sequencer/efficiencylist.go b/sequencer/efficiencylist.go new file mode 100644 index 0000000000..0508046b8d --- /dev/null +++ b/sequencer/efficiencylist.go @@ -0,0 +1,126 @@ +package sequencer + +import ( + "fmt" + "sort" + "sync" + + "github.com/0xPolygonHermez/zkevm-node/log" +) + +// efficiencyList represents a list of tx sorted by efficiency +type efficiencyList struct { + list map[string]*TxTracker + sorted []*TxTracker + mutex sync.Mutex +} + +// newEfficiencyList creates and init an efficiencyList +func newEfficiencyList() *efficiencyList { + return &efficiencyList{ + list: make(map[string]*TxTracker), + sorted: []*TxTracker{}, + } +} + +// add adds a tx to the efficiencyList +func (e *efficiencyList) add(tx *TxTracker) bool { + e.mutex.Lock() + defer e.mutex.Unlock() + + if _, found := e.list[tx.HashStr]; !found { + e.list[tx.HashStr] = tx + e.addSort(tx) + return true + } + return false +} + +// delete deletes the tx from the efficiencyList +func (e *efficiencyList) delete(tx *TxTracker) bool { + e.mutex.Lock() + defer e.mutex.Unlock() + + if tx, found := e.list[tx.HashStr]; found { + sLen := len(e.sorted) + i := sort.Search(sLen, func(i int) bool { + return e.isGreaterThan(tx, e.list[e.sorted[i].HashStr]) + }) + + if (e.sorted[i].HashStr != tx.HashStr) || i == sLen { + log.Errorf("Error deleting tx from efficiencyList: %s", tx.HashStr) + return false + } + + delete(e.list, tx.HashStr) + + copy(e.sorted[i:], e.sorted[i+1:]) + e.sorted[sLen-1] = nil + e.sorted = e.sorted[:sLen-1] + + return true + } + return false +} + +// getByIndex retrieves the tx at the i position in the sorted EfficiencyList +func (e *efficiencyList) getByIndex(i int) *TxTracker { + e.mutex.Lock() + defer e.mutex.Unlock() + + tx := e.sorted[i] + + return tx +} + +// len returns the length of the EfficiencyList +func (e *efficiencyList) len() int { + e.mutex.Lock() + defer e.mutex.Unlock() + + l := len(e.sorted) + + return l +} + +// print prints the contents of the EfficiencyList +func (e *efficiencyList) Print() { + e.mutex.Lock() + defer e.mutex.Unlock() + + fmt.Println("Len: ", len(e.sorted)) + for _, txi := range e.sorted { + fmt.Printf("Hash=%s, efficiency=%f\n", txi.HashStr, txi.Efficiency) + } +} + +// addSort adds the tx to the EfficiencyList in a sorted way +func (e *efficiencyList) addSort(tx *TxTracker) { + i := sort.Search(len(e.sorted), func(i int) bool { + return e.isGreaterThan(tx, e.list[e.sorted[i].HashStr]) + }) + + e.sorted = append(e.sorted, nil) + copy(e.sorted[i+1:], e.sorted[i:]) + e.sorted[i] = tx + log.Infof("Added tx(%s) to efficiencyList. With efficiency(%f) at index(%d) from total(%d)", tx.HashStr, tx.Efficiency, i, len(e.sorted)) +} + +// isGreaterThan returns true if the tx1 has best efficiency than tx2 +func (e *efficiencyList) isGreaterThan(tx1 *TxTracker, tx2 *TxTracker) bool { + if tx1.Efficiency > tx2.Efficiency { + return true + } else if tx1.Efficiency == tx2.Efficiency { + return tx1.HashStr >= tx2.HashStr + } else { + return false + } +} + +// GetSorted returns the sorted list of tx +func (e *efficiencyList) GetSorted() []*TxTracker { + e.mutex.Lock() + defer e.mutex.Unlock() + + return e.sorted +} diff --git a/sequencer/efficiencylist_test.go b/sequencer/efficiencylist_test.go new file mode 100644 index 0000000000..cd566edba8 --- /dev/null +++ b/sequencer/efficiencylist_test.go @@ -0,0 +1,94 @@ +package sequencer + +import ( + "crypto/rand" + "fmt" + "math/big" + "testing" + "time" +) + +// randomFloat64 is a shortcut for generating a random float between 0 and 1 using crypto/rand. +func randomFloat64() float64 { + nBig, err := rand.Int(rand.Reader, big.NewInt(1<<53)) + if err != nil { + panic(err) + } + return float64(nBig.Int64()) / (1 << 53) +} + +func TestEfficiencyListSort(t *testing.T) { + el := newEfficiencyList() + nItems := 100 + + for i := 0; i < nItems; i++ { + el.add(&TxTracker{HashStr: fmt.Sprintf("0x%d", i), Efficiency: randomFloat64()}) + } + + for i := 0; i < nItems-1; i++ { + if !(el.getByIndex(i).Efficiency > el.getByIndex(i+1).Efficiency) { + t.Fatalf("Sort error. [%d].Efficiency(%f) < [%d].Efficiency(%f)", i, el.getByIndex(i).Efficiency, i+1, el.getByIndex(i+1).Efficiency) + } + } + + // el.print() + + if el.len() != nItems { + t.Fatalf("Length error. Length %d. Expected %d", el.len(), nItems) + } +} + +func TestEfficiencyListDelete(t *testing.T) { + el := newEfficiencyList() + + el.add(&TxTracker{HashStr: "0x01", Efficiency: 1}) + el.add(&TxTracker{HashStr: "0x02", Efficiency: 2}) + el.add(&TxTracker{HashStr: "0x03", Efficiency: 2}) + el.add(&TxTracker{HashStr: "0x04", Efficiency: 3}) + el.add(&TxTracker{HashStr: "0x05", Efficiency: 10}) + el.add(&TxTracker{HashStr: "0x06", Efficiency: 1.5}) + el.add(&TxTracker{HashStr: "0x07", Efficiency: 1.5}) + + deltxs := []string{"0x03", "0x07", "0x01", "0x05"} + + for _, deltx := range deltxs { + count := el.len() + el.delete(&TxTracker{HashStr: deltx}) + + for i := 0; i < el.len(); i++ { + if el.getByIndex(i).HashStr == deltx { + t.Fatalf("Delete error. %s tx was not deleted", deltx) + } + } + + if el.len() != count-1 { + t.Fatalf("Length error. Length %d. Expected %d", el.len(), count) + } + } +} + +func TestEfficiencyListBench(t *testing.T) { + el := newEfficiencyList() + + start := time.Now() + for i := 0; i < 10000; i++ { + el.add(&TxTracker{HashStr: fmt.Sprintf("0x%d", i), Efficiency: randomFloat64()}) + } + elapsed := time.Since(start) + t.Logf("EfficiencyList adding 10000 items took %s", elapsed) + + start = time.Now() + el.add(&TxTracker{HashStr: fmt.Sprintf("0x%d", 10001), Efficiency: randomFloat64()}) + elapsed = time.Since(start) + t.Logf("EfficiencyList adding the 10001 item (efficiency=random) took %s", elapsed) + + start = time.Now() + el.add(&TxTracker{HashStr: fmt.Sprintf("0x%d", 10002), Efficiency: 0}) + elapsed = time.Since(start) + t.Logf("EfficiencyList adding the 10002 item (efficiency=0) took %s", elapsed) + + start = time.Now() + el.add(&TxTracker{HashStr: fmt.Sprintf("0x%d", 10003), Efficiency: 1000}) + elapsed = time.Since(start) + t.Logf("EfficiencyList adding the 10003 item (efficiency=1000) took %s", elapsed) +} diff --git a/sequencer/errors.go b/sequencer/errors.go new file mode 100644 index 0000000000..d12f1b2245 --- /dev/null +++ b/sequencer/errors.go @@ -0,0 +1,8 @@ +package sequencer + +import "errors" + +var ( + // ErrExpiredTransaction happens when the transaction is expired + ErrExpiredTransaction = errors.New("transaction expired") +) diff --git a/sequencer/finalizer.go b/sequencer/finalizer.go new file mode 100644 index 0000000000..0076ab6fd2 --- /dev/null +++ b/sequencer/finalizer.go @@ -0,0 +1,951 @@ +package sequencer + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "sync" + "time" + + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics" + "github.com/0xPolygonHermez/zkevm-node/state" + stateMetrics "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/ethereum/go-ethereum/common" + "github.com/jackc/pgx/v4" +) + +const oneHundred = 100 + +var ( + now = time.Now +) + +// finalizer represents the finalizer component of the sequencer. +type finalizer struct { + cfg FinalizerCfg + txsStore TxsStore + closingSignalCh ClosingSignalCh + isSynced func(ctx context.Context) bool + sequencerAddress common.Address + worker workerInterface + dbManager dbManagerInterface + executor stateInterface + batch *WipBatch + batchConstraints batchConstraints + processRequest state.ProcessRequest + sharedResourcesMux *sync.RWMutex + lastGERHash common.Hash + // closing signals + nextGER common.Hash + nextGERDeadline int64 + nextGERMux *sync.RWMutex + nextForcedBatches []state.ForcedBatch + nextForcedBatchDeadline int64 + nextForcedBatchesMux *sync.RWMutex + handlingL2Reorg bool + eventLog *event.EventLog +} + +// WipBatch represents a work-in-progress batch. +type WipBatch struct { + batchNumber uint64 + coinbase common.Address + initialStateRoot common.Hash + stateRoot common.Hash + localExitRoot common.Hash + timestamp time.Time + globalExitRoot common.Hash // 0x000...0 (ZeroHash) means to not update + remainingResources state.BatchResources + countOfTxs int + closingReason state.ClosingReason +} + +func (w *WipBatch) isEmpty() bool { + return w.countOfTxs == 0 +} + +// newFinalizer returns a new instance of Finalizer. +func newFinalizer( + cfg FinalizerCfg, + worker workerInterface, + dbManager dbManagerInterface, + executor stateInterface, + sequencerAddr common.Address, + isSynced func(ctx context.Context) bool, + closingSignalCh ClosingSignalCh, + txsStore TxsStore, + batchConstraints batchConstraints, + eventLog *event.EventLog, +) *finalizer { + return &finalizer{ + cfg: cfg, + txsStore: txsStore, + closingSignalCh: closingSignalCh, + isSynced: isSynced, + sequencerAddress: sequencerAddr, + worker: worker, + dbManager: dbManager, + executor: executor, + batch: new(WipBatch), + batchConstraints: batchConstraints, + processRequest: state.ProcessRequest{}, + sharedResourcesMux: new(sync.RWMutex), + lastGERHash: state.ZeroHash, + // closing signals + nextGER: common.Hash{}, + nextGERDeadline: 0, + nextGERMux: new(sync.RWMutex), + nextForcedBatches: make([]state.ForcedBatch, 0), + nextForcedBatchDeadline: 0, + nextForcedBatchesMux: new(sync.RWMutex), + eventLog: eventLog, + } +} + +// Start starts the finalizer. +func (f *finalizer) Start(ctx context.Context, batch *WipBatch, processingReq *state.ProcessRequest) { + var err error + if batch != nil { + f.batch = batch + } else { + f.batch, err = f.dbManager.GetWIPBatch(ctx) + if err != nil { + log.Fatalf("failed to get work-in-progress batch from DB, Err: %s", err) + } + } + + if processingReq == nil { + log.Fatal("processingReq should not be nil") + } else { + f.processRequest = *processingReq + } + + // Closing signals receiver + go f.listenForClosingSignals(ctx) + + // Processing transactions and finalizing batches + f.finalizeBatches(ctx) +} + +func (f *finalizer) SortForcedBatches(fb []state.ForcedBatch) []state.ForcedBatch { + if len(fb) == 0 { + return fb + } + // Sort by ForcedBatchNumber + for i := 0; i < len(fb)-1; i++ { + for j := i + 1; j < len(fb); j++ { + if fb[i].ForcedBatchNumber > fb[j].ForcedBatchNumber { + fb[i], fb[j] = fb[j], fb[i] + } + } + } + + return fb +} + +// listenForClosingSignals listens for signals for the batch and sets the deadline for when they need to be closed. +func (f *finalizer) listenForClosingSignals(ctx context.Context) { + for { + select { + case <-ctx.Done(): + log.Infof("finalizer closing signal listener received context done, Err: %s", ctx.Err()) + return + // ForcedBatch ch + case fb := <-f.closingSignalCh.ForcedBatchCh: + log.Debugf("finalizer received forced batch at block number: %v", fb.BlockNumber) + f.nextForcedBatchesMux.Lock() + f.nextForcedBatches = f.SortForcedBatches(append(f.nextForcedBatches, fb)) + if f.nextForcedBatchDeadline == 0 { + f.setNextForcedBatchDeadline() + } + f.nextForcedBatchesMux.Unlock() + // GlobalExitRoot ch + case ger := <-f.closingSignalCh.GERCh: + log.Debugf("finalizer received global exit root: %s", ger.String()) + f.nextGERMux.Lock() + f.nextGER = ger + if f.nextGERDeadline == 0 { + f.setNextGERDeadline() + } + f.nextGERMux.Unlock() + // L2Reorg ch + case <-f.closingSignalCh.L2ReorgCh: + log.Debug("finalizer received L2 reorg event") + f.handlingL2Reorg = true + f.halt(ctx, fmt.Errorf("L2 reorg event received")) + return + } + } +} + +// finalizeBatches runs the endless loop for processing transactions finalizing batches. +func (f *finalizer) finalizeBatches(ctx context.Context) { + log.Debug("finalizer init loop") + for { + start := now() + tx := f.worker.GetBestFittingTx(f.batch.remainingResources) + metrics.WorkerProcessingTime(time.Since(start)) + if tx != nil { + // Timestamp resolution + if f.batch.isEmpty() { + f.batch.timestamp = now() + } + + f.sharedResourcesMux.Lock() + log.Debugf("processing tx: %s", tx.Hash.Hex()) + err := f.processTransaction(ctx, tx) + if err != nil { + log.Errorf("failed to process transaction in finalizeBatches, Err: %v", err) + } + f.sharedResourcesMux.Unlock() + } else { + // wait for new txs + log.Debugf("no transactions to be processed. Sleeping for %v", f.cfg.SleepDuration.Duration) + if f.cfg.SleepDuration.Duration > 0 { + time.Sleep(f.cfg.SleepDuration.Duration) + } + } + + if f.isDeadlineEncountered() { + log.Infof("Closing batch: %d, because deadline was encountered.", f.batch.batchNumber) + f.finalizeBatch(ctx) + } else if f.isBatchFull() || f.isBatchAlmostFull() { + log.Infof("Closing batch: %d, because it's almost full.", f.batch.batchNumber) + f.finalizeBatch(ctx) + } + + if err := ctx.Err(); err != nil { + log.Infof("Stopping finalizer because of context, err: %s", err) + return + } + } +} + +func (f *finalizer) isBatchFull() bool { + if f.batch.countOfTxs >= int(f.batchConstraints.MaxTxsPerBatch) { + log.Infof("Closing batch: %d, because it's full.", f.batch.batchNumber) + f.batch.closingReason = state.BatchFullClosingReason + return true + } + return false +} + +// finalizeBatch retries to until successful closes the current batch and opens a new one, potentially processing forced batches between the batch is closed and the resulting new empty batch +func (f *finalizer) finalizeBatch(ctx context.Context) { + start := time.Now() + defer func() { + metrics.ProcessingTime(time.Since(start)) + }() + f.txsStore.Wg.Wait() + var err error + f.batch, err = f.newWIPBatch(ctx) + for err != nil { + log.Errorf("failed to create new work-in-progress batch, Err: %s", err) + f.batch, err = f.newWIPBatch(ctx) + } +} + +func (f *finalizer) halt(ctx context.Context, err error) { + event := &event.Event{ + ReceivedAt: time.Now(), + Source: event.Source_Node, + Component: event.Component_Sequencer, + Level: event.Level_Critical, + EventID: event.EventID_FinalizerHalt, + Description: fmt.Sprintf("finalizer halted due to error: %s", err), + } + + eventErr := f.eventLog.LogEvent(ctx, event) + if eventErr != nil { + log.Errorf("error storing finalizer halt event: %v", eventErr) + } + + for { + log.Errorf("fatal error: %s", err) + log.Error("halting the finalizer") + time.Sleep(5 * time.Second) //nolint:gomnd + } +} + +// newWIPBatch closes the current batch and opens a new one, potentially processing forced batches between the batch is closed and the resulting new empty batch +func (f *finalizer) newWIPBatch(ctx context.Context) (*WipBatch, error) { + f.sharedResourcesMux.Lock() + defer f.sharedResourcesMux.Unlock() + + var err error + if f.batch.stateRoot.String() == "" || f.batch.localExitRoot.String() == "" { + return nil, errors.New("state root and local exit root must have value to close batch") + } + + // We need to process the batch to update the state root before closing the batch + if f.batch.initialStateRoot == f.batch.stateRoot { + log.Info("reprocessing batch because the state root has not changed...") + err := f.processTransaction(ctx, nil) + if err != nil { + return nil, err + } + } + + // Reprocess full batch as sanity check + processBatchResponse, err := f.reprocessFullBatch(ctx, f.batch.batchNumber, f.batch.stateRoot) + if err != nil || processBatchResponse.IsRomOOCError || processBatchResponse.ExecutorError != nil { + log.Info("halting the finalizer because of a reprocessing error") + if err != nil { + f.halt(ctx, fmt.Errorf("failed to reprocess batch, err: %v", err)) + } else if processBatchResponse.IsRomOOCError { + f.halt(ctx, fmt.Errorf("out of counters during reprocessFullBath")) + } else { + f.halt(ctx, fmt.Errorf("executor error during reprocessFullBath: %v", processBatchResponse.ExecutorError)) + } + } + + // Close the current batch + err = f.closeBatch(ctx) + if err != nil { + return nil, fmt.Errorf("failed to close batch, err: %w", err) + } + + // Metadata for the next batch + stateRoot := f.batch.stateRoot + lastBatchNumber := f.batch.batchNumber + + // Process Forced Batches + if len(f.nextForcedBatches) > 0 { + lastBatchNumber, stateRoot, err = f.processForcedBatches(ctx, lastBatchNumber, stateRoot) + if err != nil { + log.Warnf("failed to process forced batch, err: %s", err) + } + } + + // Take into consideration the GER + f.nextGERMux.Lock() + if f.nextGER != state.ZeroHash { + f.lastGERHash = f.nextGER + } + f.nextGER = state.ZeroHash + f.nextGERDeadline = 0 + f.nextGERMux.Unlock() + + batch, err := f.openWIPBatch(ctx, lastBatchNumber+1, f.lastGERHash, stateRoot) + if err == nil { + f.processRequest.Timestamp = batch.timestamp + f.processRequest.BatchNumber = batch.batchNumber + f.processRequest.OldStateRoot = stateRoot + f.processRequest.GlobalExitRoot = batch.globalExitRoot + f.processRequest.Transactions = make([]byte, 0, 1) + } + + return batch, err +} + +// processTransaction processes a single transaction. +func (f *finalizer) processTransaction(ctx context.Context, tx *TxTracker) error { + var txHash string + if tx != nil { + txHash = tx.Hash.String() + } + log := log.WithFields("txHash", txHash, "batchNumber", f.processRequest.BatchNumber) + start := time.Now() + defer func() { + metrics.ProcessingTime(time.Since(start)) + }() + + if f.batch.isEmpty() { + f.processRequest.GlobalExitRoot = f.batch.globalExitRoot + } else { + f.processRequest.GlobalExitRoot = state.ZeroHash + } + + if tx != nil { + f.processRequest.Transactions = tx.RawTx + } else { + f.processRequest.Transactions = []byte{} + } + hash := "nil" + if tx != nil { + hash = tx.HashStr + } + log.Infof("processTransaction: single tx. Batch.BatchNumber: %d, BatchNumber: %d, OldStateRoot: %s, txHash: %s, GER: %s", f.batch.batchNumber, f.processRequest.BatchNumber, f.processRequest.OldStateRoot, hash, f.processRequest.GlobalExitRoot.String()) + processBatchResponse, err := f.executor.ProcessBatch(ctx, f.processRequest, true) + if err != nil { + log.Errorf("failed to process transaction: %s", err) + return err + } + + oldStateRoot := f.batch.stateRoot + if len(processBatchResponse.Responses) > 0 && tx != nil { + err = f.handleProcessTransactionResponse(ctx, tx, processBatchResponse, oldStateRoot) + if err != nil { + return err + } + } + + // Update in-memory batch and processRequest + f.processRequest.OldStateRoot = processBatchResponse.NewStateRoot + f.batch.stateRoot = processBatchResponse.NewStateRoot + f.batch.localExitRoot = processBatchResponse.NewLocalExitRoot + log.Infof("processTransaction: data loaded in memory. batch.batchNumber: %d, batchNumber: %d, result.NewStateRoot: %s, result.NewLocalExitRoot: %s, oldStateRoot: %s", f.batch.batchNumber, f.processRequest.BatchNumber, processBatchResponse.NewStateRoot.String(), processBatchResponse.NewLocalExitRoot.String(), oldStateRoot.String()) + + return nil +} + +// handleProcessTransactionResponse handles the response of transaction processing. +func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *TxTracker, result *state.ProcessBatchResponse, oldStateRoot common.Hash) error { + // Handle Transaction Error + errorCode := executor.RomErrorCode(result.Responses[0].RomError) + if !state.IsStateRootChanged(errorCode) { + // If intrinsic error or OOC error, we skip adding the transaction to the batch + f.handleProcessTransactionError(ctx, result, tx) + return result.Responses[0].RomError + } + + // Check remaining resources + err := f.checkRemainingResources(result, tx) + if err != nil { + return err + } + + // Store the processed transaction, add it to the batch and update status in the pool atomically + f.storeProcessedTx(f.batch.batchNumber, f.batch.coinbase, f.batch.timestamp, oldStateRoot, result.Responses[0], false) + f.batch.countOfTxs++ + f.updateWorkerAfterTxStored(ctx, tx, result) + + return nil +} + +// handleForcedTxsProcessResp handles the transactions responses for the processed forced batch. +func (f *finalizer) handleForcedTxsProcessResp(request state.ProcessRequest, result *state.ProcessBatchResponse, oldStateRoot common.Hash) { + log.Infof("handleForcedTxsProcessResp: batchNumber: %d, oldStateRoot: %s, newStateRoot: %s", request.BatchNumber, oldStateRoot.String(), result.NewStateRoot.String()) + for _, txResp := range result.Responses { + // Handle Transaction Error + if txResp.RomError != nil { + romErr := executor.RomErrorCode(txResp.RomError) + if executor.IsIntrinsicError(romErr) { + // If we have an intrinsic error, we should continue processing the batch, but skip the transaction + log.Errorf("handleForcedTxsProcessResp: ROM error: %s", txResp.RomError) + continue + } + } + + // Store the processed transaction, add it to the batch and update status in the pool atomically + f.storeProcessedTx(request.BatchNumber, request.Coinbase, request.Timestamp, oldStateRoot, txResp, true) + oldStateRoot = txResp.StateRoot + } +} + +func (f *finalizer) storeProcessedTx(batchNum uint64, coinbase common.Address, timestamp time.Time, previousL2BlockStateRoot common.Hash, txResponse *state.ProcessTransactionResponse, isForcedBatch bool) { + log.Infof("storeProcessedTx: storing processed tx: %s", txResponse.TxHash.String()) + f.txsStore.Wg.Wait() + f.txsStore.Wg.Add(1) + f.txsStore.Ch <- &txToStore{ + batchNumber: batchNum, + txResponse: txResponse, + coinbase: coinbase, + timestamp: uint64(timestamp.Unix()), + previousL2BlockStateRoot: previousL2BlockStateRoot, + isForcedBatch: isForcedBatch, + } + metrics.TxProcessed(metrics.TxProcessedLabelSuccessful, 1) +} + +func (f *finalizer) updateWorkerAfterTxStored(ctx context.Context, tx *TxTracker, result *state.ProcessBatchResponse) { + // Delete the transaction from the efficiency list + f.worker.DeleteTx(tx.Hash, tx.From) + log.Debug("tx deleted from efficiency list", "txHash", tx.Hash.String(), "from", tx.From.Hex()) + + start := time.Now() + txsToDelete := f.worker.UpdateAfterSingleSuccessfulTxExecution(tx.From, result.ReadWriteAddresses) + for _, txToDelete := range txsToDelete { + err := f.dbManager.UpdateTxStatus(ctx, txToDelete.Hash, pool.TxStatusFailed, false, txToDelete.FailedReason) + if err != nil { + log.Errorf("failed to update status to failed in the pool for tx: %s, err: %s", txToDelete.Hash.String(), err) + } else { + metrics.TxProcessed(metrics.TxProcessedLabelFailed, 1) + } + } + metrics.WorkerProcessingTime(time.Since(start)) +} + +// handleProcessTransactionError handles the error of a transaction +func (f *finalizer) handleProcessTransactionError(ctx context.Context, result *state.ProcessBatchResponse, tx *TxTracker) *sync.WaitGroup { + txResponse := result.Responses[0] + errorCode := executor.RomErrorCode(txResponse.RomError) + addressInfo := result.ReadWriteAddresses[tx.From] + log.Infof("handleTransactionError: error in tx: %s, errorCode: %d", tx.Hash.String(), errorCode) + wg := new(sync.WaitGroup) + failedReason := executor.RomErr(errorCode).Error() + if executor.IsROMOutOfCountersError(errorCode) { + log.Errorf("ROM out of counters error, marking tx with Hash: %s as INVALID, errorCode: %s", tx.Hash.String(), errorCode.String()) + start := time.Now() + f.worker.DeleteTx(tx.Hash, tx.From) + metrics.WorkerProcessingTime(time.Since(start)) + + wg.Add(1) + go func() { + defer wg.Done() + err := f.dbManager.UpdateTxStatus(ctx, tx.Hash, pool.TxStatusInvalid, false, &failedReason) + if err != nil { + log.Errorf("failed to update status to failed in the pool for tx: %s, err: %s", tx.Hash.String(), err) + } else { + metrics.TxProcessed(metrics.TxProcessedLabelInvalid, 1) + } + }() + } else if executor.IsInvalidNonceError(errorCode) || executor.IsInvalidBalanceError(errorCode) { + var ( + nonce *uint64 + balance *big.Int + ) + if addressInfo != nil { + nonce = addressInfo.Nonce + balance = addressInfo.Balance + } + start := time.Now() + log.Errorf("intrinsic error, moving tx with Hash: %s to NOT READY nonce(%d) balance(%s) cost(%s), err: %s", tx.Hash, nonce, balance.String(), tx.Cost.String(), txResponse.RomError) + txsToDelete := f.worker.MoveTxToNotReady(tx.Hash, tx.From, nonce, balance) + for _, txToDelete := range txsToDelete { + wg.Add(1) + txToDelete := txToDelete + go func() { + defer wg.Done() + err := f.dbManager.UpdateTxStatus(ctx, txToDelete.Hash, pool.TxStatusFailed, false, &failedReason) + metrics.TxProcessed(metrics.TxProcessedLabelFailed, 1) + if err != nil { + log.Errorf("failed to update status to failed in the pool for tx: %s, err: %s", txToDelete.Hash.String(), err) + } + }() + } + metrics.WorkerProcessingTime(time.Since(start)) + } else { + // Delete the transaction from the efficiency list + f.worker.DeleteTx(tx.Hash, tx.From) + log.Debug("tx deleted from efficiency list", "txHash", tx.Hash.String(), "from", tx.From.Hex()) + + wg.Add(1) + go func() { + defer wg.Done() + // Update the status of the transaction to failed + err := f.dbManager.UpdateTxStatus(ctx, tx.Hash, pool.TxStatusFailed, false, &failedReason) + if err != nil { + log.Errorf("failed to update status to failed in the pool for tx: %s, err: %s", tx.Hash.String(), err) + } else { + metrics.TxProcessed(metrics.TxProcessedLabelFailed, 1) + } + }() + } + + return wg +} + +// syncWithState syncs the WIP batch and processRequest with the state +func (f *finalizer) syncWithState(ctx context.Context, lastBatchNum *uint64) error { + f.sharedResourcesMux.Lock() + defer f.sharedResourcesMux.Unlock() + f.txsStore.Wg.Wait() + + var lastBatch *state.Batch + var err error + for !f.isSynced(ctx) { + log.Info("wait for synchronizer to sync last batch") + time.Sleep(time.Second) + } + if lastBatchNum == nil { + lastBatch, err = f.dbManager.GetLastBatch(ctx) + if err != nil { + return fmt.Errorf("failed to get last batch, err: %w", err) + } + } else { + lastBatch, err = f.dbManager.GetBatchByNumber(ctx, *lastBatchNum, nil) + if err != nil { + return fmt.Errorf("failed to get last batch, err: %w", err) + } + } + + batchNum := lastBatch.BatchNumber + lastBatchNum = &batchNum + + isClosed, err := f.dbManager.IsBatchClosed(ctx, *lastBatchNum) + if err != nil { + return fmt.Errorf("failed to check if batch is closed, err: %w", err) + } + log.Infof("Batch %d isClosed: %v", batchNum, isClosed) + if isClosed { + ger, _, err := f.dbManager.GetLatestGer(ctx, f.cfg.GERFinalityNumberOfBlocks) + if err != nil { + return fmt.Errorf("failed to get latest ger, err: %w", err) + } + + oldStateRoot := lastBatch.StateRoot + f.batch, err = f.openWIPBatch(ctx, *lastBatchNum+1, ger.GlobalExitRoot, oldStateRoot) + if err != nil { + return err + } + } else { + f.batch, err = f.dbManager.GetWIPBatch(ctx) + if err != nil { + return fmt.Errorf("failed to get work-in-progress batch, err: %w", err) + } + } + log.Infof("Initial Batch: %+v", f.batch) + log.Infof("Initial Batch.StateRoot: %s", f.batch.stateRoot.String()) + log.Infof("Initial Batch.GER: %s", f.batch.globalExitRoot.String()) + log.Infof("Initial Batch.Coinbase: %s", f.batch.coinbase.String()) + log.Infof("Initial Batch.InitialStateRoot: %s", f.batch.initialStateRoot.String()) + log.Infof("Initial Batch.localExitRoot: %s", f.batch.localExitRoot.String()) + + f.processRequest = state.ProcessRequest{ + BatchNumber: *lastBatchNum, + OldStateRoot: f.batch.stateRoot, + GlobalExitRoot: f.batch.globalExitRoot, + Coinbase: f.sequencerAddress, + Timestamp: f.batch.timestamp, + Transactions: make([]byte, 0, 1), + Caller: stateMetrics.SequencerCallerLabel, + } + + log.Infof("synced with state, lastBatchNum: %d. State root: %s", *lastBatchNum, f.batch.initialStateRoot.Hex()) + + return nil +} + +// processForcedBatches processes all the forced batches that are pending to be processed +func (f *finalizer) processForcedBatches(ctx context.Context, lastBatchNumberInState uint64, stateRoot common.Hash) (uint64, common.Hash, error) { + f.nextForcedBatchesMux.Lock() + defer f.nextForcedBatchesMux.Unlock() + f.nextForcedBatchDeadline = 0 + + lastTrustedForcedBatchNumber, err := f.dbManager.GetLastTrustedForcedBatchNumber(ctx, nil) + if err != nil { + return 0, common.Hash{}, fmt.Errorf("failed to get last trusted forced batch number, err: %w", err) + } + nextForcedBatchNum := lastTrustedForcedBatchNumber + 1 + + for _, forcedBatch := range f.nextForcedBatches { + // Skip already processed forced batches + if forcedBatch.ForcedBatchNumber < nextForcedBatchNum { + continue + } + // Process in-between unprocessed forced batches + for forcedBatch.ForcedBatchNumber > nextForcedBatchNum { + lastBatchNumberInState, stateRoot = f.processForcedBatch(ctx, lastBatchNumberInState, stateRoot, forcedBatch) + nextForcedBatchNum += 1 + } + // Process the current forced batch from the channel queue + lastBatchNumberInState, stateRoot = f.processForcedBatch(ctx, lastBatchNumberInState, stateRoot, forcedBatch) + nextForcedBatchNum += 1 + } + f.nextForcedBatches = make([]state.ForcedBatch, 0) + + return lastBatchNumberInState, stateRoot, nil +} + +func (f *finalizer) processForcedBatch(ctx context.Context, lastBatchNumberInState uint64, stateRoot common.Hash, forcedBatch state.ForcedBatch) (uint64, common.Hash) { + request := state.ProcessRequest{ + BatchNumber: lastBatchNumberInState + 1, + OldStateRoot: stateRoot, + GlobalExitRoot: forcedBatch.GlobalExitRoot, + Transactions: forcedBatch.RawTxsData, + Coinbase: f.sequencerAddress, + Timestamp: now(), + Caller: stateMetrics.SequencerCallerLabel, + } + response, err := f.dbManager.ProcessForcedBatch(forcedBatch.ForcedBatchNumber, request) + if err != nil { + // If there is EXECUTOR (Batch level) error, halt the finalizer. + f.halt(ctx, fmt.Errorf("failed to process forced batch, Executor err: %w", err)) + return lastBatchNumberInState, stateRoot + } + + stateRoot = response.NewStateRoot + lastBatchNumberInState += 1 + f.nextGERMux.Lock() + f.lastGERHash = forcedBatch.GlobalExitRoot + f.nextGERMux.Unlock() + if len(response.Responses) > 0 && !response.IsRomOOCError { + f.handleForcedTxsProcessResp(request, response, stateRoot) + } + + return lastBatchNumberInState, stateRoot +} + +// openWIPBatch opens a new batch in the state and returns it as WipBatch +func (f *finalizer) openWIPBatch(ctx context.Context, batchNum uint64, ger, stateRoot common.Hash) (*WipBatch, error) { + dbTx, err := f.dbManager.BeginStateTransaction(ctx) + if err != nil { + return nil, fmt.Errorf("failed to begin state transaction to open batch, err: %w", err) + } + + // open next batch + openBatchResp, err := f.openBatch(ctx, batchNum, ger, dbTx) + if err != nil { + if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { + return nil, fmt.Errorf( + "failed to rollback dbTx: %s. Rollback err: %w", + rollbackErr.Error(), err, + ) + } + return nil, err + } + if err := dbTx.Commit(ctx); err != nil { + return nil, fmt.Errorf("failed to commit database transaction for opening a batch, err: %w", err) + } + + // Check if synchronizer is up-to-date + for !f.isSynced(ctx) { + log.Info("wait for synchronizer to sync last batch") + time.Sleep(time.Second) + } + + return &WipBatch{ + batchNumber: batchNum, + coinbase: f.sequencerAddress, + initialStateRoot: stateRoot, + stateRoot: stateRoot, + timestamp: openBatchResp.Timestamp, + globalExitRoot: ger, + remainingResources: getMaxRemainingResources(f.batchConstraints), + }, err +} + +// closeBatch closes the current batch in the state +func (f *finalizer) closeBatch(ctx context.Context) error { + transactions, err := f.dbManager.GetTransactionsByBatchNumber(ctx, f.batch.batchNumber) + if err != nil { + return fmt.Errorf("failed to get transactions from transactions, err: %w", err) + } + for i, tx := range transactions { + log.Infof("closeBatch: BatchNum: %d, Tx position: %d, txHash: %s", f.batch.batchNumber, i, tx.Hash().String()) + } + usedResources := getUsedBatchResources(f.batchConstraints, f.batch.remainingResources) + receipt := ClosingBatchParameters{ + BatchNumber: f.batch.batchNumber, + StateRoot: f.batch.stateRoot, + LocalExitRoot: f.batch.localExitRoot, + Txs: transactions, + BatchResources: usedResources, + ClosingReason: f.batch.closingReason, + } + return f.dbManager.CloseBatch(ctx, receipt) +} + +// openBatch opens a new batch in the state +func (f *finalizer) openBatch(ctx context.Context, num uint64, ger common.Hash, dbTx pgx.Tx) (state.ProcessingContext, error) { + processingCtx := state.ProcessingContext{ + BatchNumber: num, + Coinbase: f.sequencerAddress, + Timestamp: now(), + GlobalExitRoot: ger, + } + err := f.dbManager.OpenBatch(ctx, processingCtx, dbTx) + if err != nil { + return state.ProcessingContext{}, fmt.Errorf("failed to open new batch, err: %w", err) + } + + return processingCtx, nil +} + +// reprocessBatch reprocesses a batch used as sanity check +func (f *finalizer) reprocessFullBatch(ctx context.Context, batchNum uint64, expectedStateRoot common.Hash) (*state.ProcessBatchResponse, error) { + batch, err := f.dbManager.GetBatchByNumber(ctx, batchNum, nil) + if err != nil { + return nil, fmt.Errorf("failed to get batch by number, err: %v", err) + } + processRequest := state.ProcessRequest{ + BatchNumber: batch.BatchNumber, + GlobalExitRoot: batch.GlobalExitRoot, + OldStateRoot: f.batch.initialStateRoot, + Transactions: batch.BatchL2Data, + Coinbase: batch.Coinbase, + Timestamp: batch.Timestamp, + Caller: stateMetrics.DiscardCallerLabel, + } + log.Infof("reprocessFullBatch: BatchNumber: %d, OldStateRoot: %s, Ger: %s", batch.BatchNumber, f.batch.initialStateRoot.String(), batch.GlobalExitRoot.String()) + txs, _, err := state.DecodeTxs(batch.BatchL2Data) + if err != nil { + log.Errorf("reprocessFullBatch: error decoding BatchL2Data before reprocessing full batch: %d. Error: %v", batch.BatchNumber, err) + return nil, fmt.Errorf("reprocessFullBatch: error decoding BatchL2Data before reprocessing full batch: %d. Error: %v", batch.BatchNumber, err) + } + for i, tx := range txs { + log.Infof("reprocessFullBatch: Tx position %d. TxHash: %s", i, tx.Hash()) + } + + result, err := f.executor.ProcessBatch(ctx, processRequest, false) + if err != nil { + log.Errorf("failed to process batch, err: %s", err) + return nil, err + } + + if result.IsRomOOCError { + log.Errorf("failed to process batch %v because OutOfCounters", batch.BatchNumber) + payload, err := json.Marshal(processRequest) + if err != nil { + log.Errorf("error marshaling payload: %v", err) + } else { + event := &event.Event{ + ReceivedAt: time.Now(), + Source: event.Source_Node, + Component: event.Component_Sequencer, + Level: event.Level_Critical, + EventID: event.EventID_ReprocessFullBatchOOC, + Description: string(payload), + Json: processRequest, + } + err = f.eventLog.LogEvent(ctx, event) + if err != nil { + log.Errorf("error storing payload: %v", err) + } + } + return nil, fmt.Errorf("failed to process batch because OutOfCounters error") + } + + if result.NewStateRoot != expectedStateRoot { + log.Errorf("batchNumber: %d, reprocessed batch has different state root, expected: %s, got: %s", batch.BatchNumber, expectedStateRoot.Hex(), result.NewStateRoot.Hex()) + return nil, fmt.Errorf("batchNumber: %d, reprocessed batch has different state root, expected: %s, got: %s", batch.BatchNumber, expectedStateRoot.Hex(), result.NewStateRoot.Hex()) + } + + return result, nil +} + +func (f *finalizer) getLastBatchNumAndOldStateRoot(ctx context.Context) (uint64, common.Hash, error) { + const two = 2 + var oldStateRoot common.Hash + batches, err := f.dbManager.GetLastNBatches(ctx, two) + if err != nil { + return 0, common.Hash{}, fmt.Errorf("failed to get last %d batches, err: %w", two, err) + } + lastBatch := batches[0] + + oldStateRoot = f.getOldStateRootFromBatches(batches) + return lastBatch.BatchNumber, oldStateRoot, nil +} + +func (f *finalizer) getOldStateRootFromBatches(batches []*state.Batch) common.Hash { + const one = 1 + const two = 2 + var oldStateRoot common.Hash + if len(batches) == one { + oldStateRoot = batches[0].StateRoot + } else if len(batches) == two { + oldStateRoot = batches[1].StateRoot + } + + return oldStateRoot +} + +// isDeadlineEncountered returns true if any closing signal deadline is encountered +func (f *finalizer) isDeadlineEncountered() bool { + // Forced batch deadline + if f.nextForcedBatchDeadline != 0 && now().Unix() >= f.nextForcedBatchDeadline { + log.Infof("Closing batch: %d, forced batch deadline encountered.", f.batch.batchNumber) + return true + } + // Global Exit Root deadline + if f.nextGERDeadline != 0 && now().Unix() >= f.nextGERDeadline { + log.Infof("Closing batch: %d, Global Exit Root deadline encountered.", f.batch.batchNumber) + f.batch.closingReason = state.GlobalExitRootDeadlineClosingReason + return true + } + // Timestamp resolution deadline + if !f.batch.isEmpty() && f.batch.timestamp.Add(f.cfg.TimestampResolution.Duration).Before(time.Now()) { + log.Infof("Closing batch: %d, because of timestamp resolution.", f.batch.batchNumber) + f.batch.closingReason = state.TimeoutResolutionDeadlineClosingReason + return true + } + return false +} + +// checkRemainingResources checks if the transaction uses less resources than the remaining ones in the batch. +func (f *finalizer) checkRemainingResources(result *state.ProcessBatchResponse, tx *TxTracker) error { + usedResources := state.BatchResources{ + ZKCounters: result.UsedZkCounters, + Bytes: uint64(len(tx.RawTx)), + } + + err := f.batch.remainingResources.Sub(usedResources) + if err != nil { + log.Infof("current transaction exceeds the batch limit, updating metadata for tx in worker and continuing") + start := time.Now() + f.worker.UpdateTx(result.Responses[0].TxHash, tx.From, usedResources.ZKCounters) + metrics.WorkerProcessingTime(time.Since(start)) + return err + } + + return nil +} + +// isBatchAlmostFull checks if the current batch remaining resources are under the constraints threshold for most efficient moment to close a batch +func (f *finalizer) isBatchAlmostFull() bool { + resources := f.batch.remainingResources + zkCounters := resources.ZKCounters + result := false + resourceDesc := "" + if resources.Bytes <= f.getConstraintThresholdUint64(f.batchConstraints.MaxBatchBytesSize) { + resourceDesc = "MaxBatchBytesSize" + result = true + } else if zkCounters.UsedSteps <= f.getConstraintThresholdUint32(f.batchConstraints.MaxSteps) { + resourceDesc = "MaxSteps" + result = true + } else if zkCounters.UsedPoseidonPaddings <= f.getConstraintThresholdUint32(f.batchConstraints.MaxPoseidonPaddings) { + resourceDesc = "MaxPoseidonPaddings" + result = true + } else if zkCounters.UsedBinaries <= f.getConstraintThresholdUint32(f.batchConstraints.MaxBinaries) { + resourceDesc = "MaxBinaries" + result = true + } else if zkCounters.UsedKeccakHashes <= f.getConstraintThresholdUint32(f.batchConstraints.MaxKeccakHashes) { + resourceDesc = "MaxKeccakHashes" + result = true + } else if zkCounters.UsedArithmetics <= f.getConstraintThresholdUint32(f.batchConstraints.MaxArithmetics) { + resourceDesc = "MaxArithmetics" + result = true + } else if zkCounters.UsedMemAligns <= f.getConstraintThresholdUint32(f.batchConstraints.MaxMemAligns) { + resourceDesc = "MaxMemAligns" + result = true + } else if zkCounters.CumulativeGasUsed <= f.getConstraintThresholdUint64(f.batchConstraints.MaxCumulativeGasUsed) { + resourceDesc = "MaxCumulativeGasUsed" + result = true + } + + if result { + log.Infof("Closing batch: %d, because it reached %s threshold limit", f.batch.batchNumber, resourceDesc) + f.batch.closingReason = state.BatchAlmostFullClosingReason + } + + return result +} + +func (f *finalizer) setNextForcedBatchDeadline() { + f.nextForcedBatchDeadline = now().Unix() + int64(f.cfg.ForcedBatchDeadlineTimeout.Duration.Seconds()) +} + +func (f *finalizer) setNextGERDeadline() { + f.nextGERDeadline = now().Unix() + int64(f.cfg.GERDeadlineTimeout.Duration.Seconds()) +} + +func (f *finalizer) getConstraintThresholdUint64(input uint64) uint64 { + return input * uint64(f.cfg.ResourcePercentageToCloseBatch) / oneHundred +} + +func (f *finalizer) getConstraintThresholdUint32(input uint32) uint32 { + return uint32(input*f.cfg.ResourcePercentageToCloseBatch) / oneHundred +} + +func getUsedBatchResources(constraints batchConstraints, remainingResources state.BatchResources) state.BatchResources { + return state.BatchResources{ + ZKCounters: state.ZKCounters{ + CumulativeGasUsed: constraints.MaxCumulativeGasUsed - remainingResources.ZKCounters.CumulativeGasUsed, + UsedKeccakHashes: constraints.MaxKeccakHashes - remainingResources.ZKCounters.UsedKeccakHashes, + UsedPoseidonHashes: constraints.MaxPoseidonHashes - remainingResources.ZKCounters.UsedPoseidonHashes, + UsedPoseidonPaddings: constraints.MaxPoseidonPaddings - remainingResources.ZKCounters.UsedPoseidonPaddings, + UsedMemAligns: constraints.MaxMemAligns - remainingResources.ZKCounters.UsedMemAligns, + UsedArithmetics: constraints.MaxArithmetics - remainingResources.ZKCounters.UsedArithmetics, + UsedBinaries: constraints.MaxBinaries - remainingResources.ZKCounters.UsedBinaries, + UsedSteps: constraints.MaxSteps - remainingResources.ZKCounters.UsedSteps, + }, + Bytes: constraints.MaxBatchBytesSize - remainingResources.Bytes, + } +} diff --git a/sequencer/finalizer_test.go b/sequencer/finalizer_test.go new file mode 100644 index 0000000000..8e32e78c67 --- /dev/null +++ b/sequencer/finalizer_test.go @@ -0,0 +1,1135 @@ +package sequencer + +import ( + "context" + "fmt" + "math/big" + "sync" + "testing" + "time" + + cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +var ( + f *finalizer + nilErr error + dbManagerMock = new(DbManagerMock) + executorMock = new(StateMock) + workerMock = new(WorkerMock) + dbTxMock = new(DbTxMock) + bc = batchConstraints{ + MaxTxsPerBatch: 150, + MaxBatchBytesSize: 129848, + MaxCumulativeGasUsed: 30000000, + MaxKeccakHashes: 468, + MaxPoseidonHashes: 279620, + MaxPoseidonPaddings: 149796, + MaxMemAligns: 262144, + MaxArithmetics: 262144, + MaxBinaries: 262144, + MaxSteps: 8388608, + } + txsStore = TxsStore{ + Ch: make(chan *txToStore, 1), + Wg: new(sync.WaitGroup), + } + closingSignalCh = ClosingSignalCh{ + ForcedBatchCh: make(chan state.ForcedBatch), + GERCh: make(chan common.Hash), + L2ReorgCh: make(chan L2ReorgEvent), + } + cfg = FinalizerCfg{ + GERDeadlineTimeout: cfgTypes.Duration{ + Duration: 60, + }, + ForcedBatchDeadlineTimeout: cfgTypes.Duration{ + Duration: 60, + }, + SleepDuration: cfgTypes.Duration{ + Duration: 60, + }, + ClosingSignalsManagerWaitForCheckingL1Timeout: cfgTypes.Duration{ + Duration: 10 * time.Second, + }, + ClosingSignalsManagerWaitForCheckingGER: cfgTypes.Duration{ + Duration: 10 * time.Second, + }, + ClosingSignalsManagerWaitForCheckingForcedBatches: cfgTypes.Duration{ + Duration: 10 * time.Second, + }, + ResourcePercentageToCloseBatch: 10, + GERFinalityNumberOfBlocks: 64, + } + seqAddr = common.Address{} + oldHash = common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f2") + newHash = common.HexToHash("0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + sender = common.HexToAddress("0x3445324") + isSynced = func(ctx context.Context) bool { + return true + } + // tx1 = ethTypes.NewTransaction(0, common.HexToAddress("0"), big.NewInt(0), 0, big.NewInt(0), []byte("aaa")) + // tx2 = ethTypes.NewTransaction(1, common.HexToAddress("1"), big.NewInt(1), 0, big.NewInt(1), []byte("bbb")) + + testErr = fmt.Errorf("some error") + // testErr2 = fmt.Errorf("some error2") + openBatchError = fmt.Errorf("failed to open new batch, err: %w", testErr) + cumulativeGasErr = state.GetZKCounterError("CumulativeGasUsed") +) + +func testNow() time.Time { + return time.Unix(0, 0) +} + +func TestNewFinalizer(t *testing.T) { + eventStorage, err := nileventstorage.NewNilEventStorage() + require.NoError(t, err) + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + // arrange and act + f = newFinalizer(cfg, workerMock, dbManagerMock, executorMock, seqAddr, isSynced, closingSignalCh, txsStore, bc, eventLog) + + // assert + assert.NotNil(t, f) + assert.Equal(t, f.cfg, cfg) + assert.Equal(t, f.worker, workerMock) + assert.Equal(t, f.dbManager, dbManagerMock) + assert.Equal(t, f.executor, executorMock) + assert.Equal(t, f.sequencerAddress, seqAddr) + assert.Equal(t, f.closingSignalCh, closingSignalCh) + assert.Equal(t, f.txsStore, txsStore) + assert.Equal(t, f.batchConstraints, bc) +} + +// +//func TestFinalizer_newWIPBatch(t *testing.T) { +// // arrange +// f = setupFinalizer(true) +// now = testNow +// defer func() { +// now = time.Now +// }() +// +// txs := make([]types.Transaction, 0) +// batchNum := f.batch.batchNumber + 1 +// f.processRequest.GlobalExitRoot = oldHash +// f.processRequest.OldStateRoot = oldHash +// f.processRequest.Transactions = []byte{} +// expectedWipBatch := &WipBatch{ +// batchNumber: batchNum, +// coinbase: f.sequencerAddress, +// initialStateRoot: newHash, +// stateRoot: newHash, +// timestamp: uint64(now().Unix()), +// remainingResources: getMaxRemainingResources(f.batchConstraints), +// } +// closeBatchParams := ClosingBatchParameters{ +// BatchNumber: f.batch.batchNumber, +// StateRoot: f.batch.stateRoot, +// LocalExitRoot: f.batch.localExitRoot, +// Txs: txs, +// } +// batches := []*state.Batch{ +// { +// BatchNumber: 0, +// StateRoot: oldHash, +// }, +// } +// testCases := []struct { +// name string +// batches []*state.Batch +// closeBatchErr error +// closeBatchParams ClosingBatchParameters +// openBatchErr error +// expectedWip *WipBatch +// expectedErr error +// }{ +// { +// name: "Success", +// expectedWip: expectedWipBatch, +// closeBatchParams: closeBatchParams, +// batches: batches, +// }, +// { +// name: "Close Batch Error", +// expectedWip: expectedWipBatch, +// closeBatchParams: closeBatchParams, +// batches: batches, +// closeBatchErr: testErr, +// expectedErr: fmt.Errorf("failed to close batch, err: %w", testErr), +// }, +// { +// name: "Open Batch Error", +// expectedWip: expectedWipBatch, +// closeBatchParams: closeBatchParams, +// batches: batches, +// openBatchErr: testErr, +// expectedErr: fmt.Errorf("failed to open new batch, err: %w", testErr), +// }, +// } +// for _, tc := range testCases { +// t.Run(tc.name, func(t *testing.T) { +// // arrange +// dbManagerMock.On("CloseBatch", ctx, tc.closeBatchParams).Return(tc.closeBatchErr).Once() +// executorMock.On("ProcessBatch", ctx, f.processRequest).Return(&state.ProcessBatchResponse{ +// IsBatchProcessed: true, +// }, nilErr).Once() +// +// if tc.expectedErr == nil { +// dbManagerMock.On("GetTransactionsByBatchNumber", ctx, f.batch.batchNumber).Return(txs, nilErr).Once() +// } +// +// if tc.closeBatchErr == nil { +// dbManagerMock.On("BeginStateTransaction", ctx).Return(dbTxMock, nilErr).Once() +// dbManagerMock.On("OpenBatch", ctx, mock.Anything, dbTxMock).Return(tc.openBatchErr).Once() +// +// // Async Calls from reprocessBatch +// dbManagerMock.On("GetLastNBatches", ctx, uint(2)).Return(tc.batches, nilErr).Maybe() +// dbManagerMock.On("GetTransactionsByBatchNumber", ctx, f.batch.batchNumber).Return(txs, nilErr).Maybe() +// processRequest := f.processRequest +// processRequest.Caller = state.DiscardCallerLabel +// processRequest.Timestamp = f.batch.timestamp +// executorMock.On("ProcessBatch", ctx, processRequest).Return(&state.ProcessBatchResponse{ +// NewStateRoot: f.batch.stateRoot, +// NewLocalExitRoot: f.batch.localExitRoot, +// +// IsBatchProcessed: true, +// }, nilErr).Maybe() +// +// if tc.openBatchErr == nil { +// dbTxMock.On("Commit", ctx).Return(nilErr).Once() +// } else { +// dbTxMock.On("Rollback", ctx).Return(nilErr).Once() +// } +// } +// +// // act +// wipBatch, err := f.newWIPBatch(ctx) +// +// // assert +// if tc.expectedErr != nil { +// assert.Error(t, err) +// assert.EqualError(t, err, tc.expectedErr.Error()) +// assert.Nil(t, wipBatch) +// } else { +// assert.NoError(t, err) +// assert.Equal(t, tc.expectedWip, wipBatch) +// } +// dbManagerMock.AssertExpectations(t) +// dbTxMock.AssertExpectations(t) +// }) +// } +//} + +func TestFinalizer_syncWithState(t *testing.T) { + // arrange + f = setupFinalizer(true) + now = testNow + defer func() { + now = time.Now + }() + one := uint64(1) + batches := []*state.Batch{ + { + BatchNumber: 1, + StateRoot: oldHash, + GlobalExitRoot: oldHash, + }, + } + testCases := []struct { + name string + batches []*state.Batch + lastBatchNum *uint64 + isBatchClosed bool + ger common.Hash + getWIPBatchErr error + openBatchErr error + isBatchClosedErr error + getLastBatchErr error + expectedProcessingCtx state.ProcessingContext + expectedBatch *WipBatch + expectedErr error + }{ + { + name: "Success-Closed Batch", + lastBatchNum: &one, + isBatchClosed: true, + ger: oldHash, + batches: batches, + expectedBatch: &WipBatch{ + batchNumber: one + 1, + coinbase: f.sequencerAddress, + initialStateRoot: oldHash, + stateRoot: oldHash, + timestamp: testNow(), + globalExitRoot: oldHash, + remainingResources: getMaxRemainingResources(f.batchConstraints), + }, + expectedProcessingCtx: state.ProcessingContext{ + BatchNumber: one + 1, + Coinbase: f.sequencerAddress, + Timestamp: testNow(), + GlobalExitRoot: oldHash, + }, + expectedErr: nil, + }, + { + name: "Success-Open Batch", + lastBatchNum: &one, + isBatchClosed: false, + batches: batches, + ger: common.Hash{}, + expectedBatch: &WipBatch{ + batchNumber: one, + coinbase: f.sequencerAddress, + initialStateRoot: oldHash, + stateRoot: oldHash, + timestamp: testNow(), + globalExitRoot: oldHash, + remainingResources: getMaxRemainingResources(f.batchConstraints), + }, + expectedProcessingCtx: state.ProcessingContext{ + BatchNumber: one, + Coinbase: f.sequencerAddress, + Timestamp: testNow(), + GlobalExitRoot: oldHash, + }, + }, + { + name: "Error-Failed to get last batch", + lastBatchNum: nil, + batches: batches, + isBatchClosed: true, + ger: oldHash, + getLastBatchErr: testErr, + expectedErr: fmt.Errorf("failed to get last batch, err: %w", testErr), + }, + { + name: "Error-Failed to check if batch is closed", + lastBatchNum: &one, + batches: batches, + isBatchClosed: true, + ger: oldHash, + isBatchClosedErr: testErr, + expectedErr: fmt.Errorf("failed to check if batch is closed, err: %w", testErr), + }, + { + name: "Error-Failed to get work-in-progress batch", + lastBatchNum: &one, + batches: batches, + isBatchClosed: false, + ger: common.Hash{}, + getWIPBatchErr: testErr, + expectedErr: fmt.Errorf("failed to get work-in-progress batch, err: %w", testErr), + }, + { + name: "Error-Failed to open new batch", + lastBatchNum: &one, + batches: batches, + isBatchClosed: true, + ger: oldHash, + openBatchErr: testErr, + expectedProcessingCtx: state.ProcessingContext{ + BatchNumber: one + 1, + Coinbase: f.sequencerAddress, + Timestamp: testNow(), + GlobalExitRoot: oldHash, + }, + expectedErr: fmt.Errorf("failed to open new batch, err: %w", testErr), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + if tc.lastBatchNum == nil { + dbManagerMock.Mock.On("GetLastBatch", ctx).Return(tc.batches[0], tc.getLastBatchErr).Once() + } else { + dbManagerMock.On("GetBatchByNumber", ctx, *tc.lastBatchNum, nil).Return(tc.batches[0], nilErr).Once() + } + + if tc.getLastBatchErr == nil { + dbManagerMock.Mock.On("IsBatchClosed", ctx, *tc.lastBatchNum).Return(tc.isBatchClosed, tc.isBatchClosedErr).Once() + } + + if tc.isBatchClosed { + if tc.getLastBatchErr == nil && tc.isBatchClosedErr == nil { + dbManagerMock.On("OpenBatch", ctx, tc.expectedProcessingCtx, dbTxMock).Return(tc.openBatchErr).Once() + } + + if tc.getLastBatchErr == nil && tc.isBatchClosedErr == nil { + dbManagerMock.Mock.On("GetLatestGer", ctx, f.cfg.GERFinalityNumberOfBlocks).Return(state.GlobalExitRoot{GlobalExitRoot: tc.ger}, testNow(), nil).Once() + dbManagerMock.On("BeginStateTransaction", ctx).Return(dbTxMock, nil).Once() + if tc.openBatchErr == nil { + dbTxMock.On("Commit", ctx).Return(nil).Once() + } + } + if tc.expectedErr != nil && tc.openBatchErr != nil { + dbTxMock.On("Rollback", ctx).Return(nil).Once() + } + } else { + dbManagerMock.Mock.On("GetWIPBatch", ctx).Return(tc.expectedBatch, tc.getWIPBatchErr).Once() + } + + // act + err := f.syncWithState(ctx, tc.lastBatchNum) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedBatch, f.batch) + } + dbManagerMock.AssertExpectations(t) + }) + } +} + +//func TestFinalizer_processForcedBatches(t *testing.T) { +// // arrange +// var err error +// f = setupFinalizer(false) +// now = testNow +// defer func() { +// now = time.Now +// }() +// RawTxsData1 := make([]byte, 0, 2) +// RawTxsData1 = append(RawTxsData1, []byte("forced tx 1")...) +// RawTxsData1 = append(RawTxsData1, []byte("forced tx 2")...) +// RawTxsData2 := make([]byte, 0, 2) +// RawTxsData2 = append(RawTxsData2, []byte("forced tx 3")...) +// RawTxsData2 = append(RawTxsData2, []byte("forced tx 4")...) +// batchNumber := f.batch.batchNumber +// stateRoot := oldHash +// forcedBatch1 := state.ForcedBatch{ +// ForcedBatchNumber: 2, +// GlobalExitRoot: oldHash, +// RawTxsData: RawTxsData1, +// } +// forcedBatch2 := state.ForcedBatch{ +// ForcedBatchNumber: 3, +// GlobalExitRoot: oldHash, +// RawTxsData: RawTxsData2, +// } +// testCases := []struct { +// name string +// forcedBatch []state.ForcedBatch +// getLastTrustedForcedBatchNumErr error +// expectedErr error +// }{ +// { +// name: "Success", +// forcedBatch: []state.ForcedBatch{forcedBatch1, forcedBatch2}, +// }, +// { +// name: "GetLastTrustedForcedBatchNumber_Error", +// forcedBatch: []state.ForcedBatch{forcedBatch1}, +// getLastTrustedForcedBatchNumErr: testErr, +// expectedErr: fmt.Errorf("failed to get last trusted forced batch number, err: %s", testErr), +// }, +// } +// +// for _, tc := range testCases { +// t.Run(tc.name, func(t *testing.T) { +// // arrange +// f.nextForcedBatches = tc.forcedBatch +// internalBatchNumber := batchNumber +// dbManagerMock.On("BeginStateTransaction", ctx).Return(dbTxMock, nil).Once() +// dbManagerMock.On("GetLastTrustedForcedBatchNumber", ctx, dbTxMock).Return(uint64(1), tc.getLastTrustedForcedBatchNumErr).Once() +// +// for _, forcedBatch := range tc.forcedBatch { +// internalBatchNumber += 1 +// processRequest := state.ProcessRequest{ +// BatchNumber: internalBatchNumber, +// OldStateRoot: stateRoot, +// GlobalExitRoot: forcedBatch.GlobalExitRoot, +// Transactions: forcedBatch.RawTxsData, +// Coinbase: f.sequencerAddress, +// Timestamp: now(), +// Caller: stateMetrics.SequencerCallerLabel, +// } +// dbManagerMock.On("ProcessForcedBatch", forcedBatch.ForcedBatchNumber, processRequest).Return(&state.ProcessBatchResponse{ +// NewStateRoot: stateRoot, +// NewBatchNumber: internalBatchNumber, +// }, nilErr).Once() +// } +// +// // act +// batchNumber, stateRoot, err = f.processForcedBatches(ctx, batchNumber, stateRoot) +// +// // assert +// if tc.expectedErr != nil { +// assert.EqualError(t, err, tc.expectedErr.Error()) +// } else { +// assert.NoError(t, tc.expectedErr) +// dbManagerMock.AssertExpectations(t) +// } +// }) +// } +//} + +func TestFinalizer_openWIPBatch(t *testing.T) { + // arrange + f = setupFinalizer(true) + now = testNow + defer func() { + now = time.Now + }() + batchNum := f.batch.batchNumber + 1 + expectedWipBatch := &WipBatch{ + batchNumber: batchNum, + coinbase: f.sequencerAddress, + initialStateRoot: oldHash, + stateRoot: oldHash, + timestamp: now(), + globalExitRoot: oldHash, + remainingResources: getMaxRemainingResources(f.batchConstraints), + } + testCases := []struct { + name string + openBatchErr error + beginTxErr error + commitErr error + rollbackErr error + expectedWip *WipBatch + expectedErr error + }{ + { + name: "Success", + expectedWip: expectedWipBatch, + }, + { + name: "BeginTransaction Error", + beginTxErr: testErr, + expectedErr: fmt.Errorf("failed to begin state transaction to open batch, err: %w", testErr), + }, + { + name: "OpenBatch Error", + openBatchErr: testErr, + expectedErr: fmt.Errorf("failed to open new batch, err: %w", testErr), + }, + { + name: "Commit Error", + commitErr: testErr, + expectedErr: fmt.Errorf("failed to commit database transaction for opening a batch, err: %w", testErr), + }, + { + name: "Rollback Error", + openBatchErr: testErr, + rollbackErr: testErr, + expectedErr: fmt.Errorf( + "failed to rollback dbTx: %s. Rollback err: %w", + testErr.Error(), openBatchError, + ), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + dbManagerMock.On("BeginStateTransaction", ctx).Return(dbTxMock, tc.beginTxErr).Once() + if tc.beginTxErr == nil { + dbManagerMock.On("OpenBatch", ctx, mock.Anything, dbTxMock).Return(tc.openBatchErr).Once() + } + + if tc.expectedErr != nil && (tc.rollbackErr != nil || tc.openBatchErr != nil) { + dbTxMock.On("Rollback", ctx).Return(tc.rollbackErr).Once() + } + + if tc.expectedErr == nil || tc.commitErr != nil { + dbTxMock.On("Commit", ctx).Return(tc.commitErr).Once() + } + + // act + wipBatch, err := f.openWIPBatch(ctx, batchNum, oldHash, oldHash) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + assert.Nil(t, wipBatch) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedWip, wipBatch) + } + dbManagerMock.AssertExpectations(t) + dbTxMock.AssertExpectations(t) + }) + } +} + +// TestFinalizer_closeBatch tests the closeBatch method. +func TestFinalizer_closeBatch(t *testing.T) { + // arrange + f = setupFinalizer(true) + txs := make([]types.Transaction, 0) + usedResources := getUsedBatchResources(f.batchConstraints, f.batch.remainingResources) + receipt := ClosingBatchParameters{ + BatchNumber: f.batch.batchNumber, + StateRoot: f.batch.stateRoot, + LocalExitRoot: f.processRequest.GlobalExitRoot, + BatchResources: usedResources, + Txs: txs, + } + managerErr := fmt.Errorf("some error") + testCases := []struct { + name string + managerErr error + expectedErr error + }{ + { + name: "Success", + managerErr: nil, + expectedErr: nil, + }, + { + name: "Manager Error", + managerErr: managerErr, + expectedErr: fmt.Errorf("failed to get transactions from transactions, err: %w", managerErr), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + dbManagerMock.Mock.On("CloseBatch", ctx, receipt).Return(tc.managerErr).Once() + dbManagerMock.Mock.On("GetTransactionsByBatchNumber", ctx, receipt.BatchNumber).Return(txs, tc.managerErr).Once() + + // act + err := f.closeBatch(ctx) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + assert.ErrorIs(t, err, tc.managerErr) + } else { + assert.NoError(t, err) + } + }) + } +} + +func TestFinalizer_openBatch(t *testing.T) { + // arrange + f = setupFinalizer(true) + now = testNow + defer func() { + now = time.Now + }() + batchNum := f.batch.batchNumber + 1 + testCases := []struct { + name string + batchNum uint64 + managerErr error + expectedCtx state.ProcessingContext + expectedErr error + }{ + { + name: "Success", + batchNum: batchNum, + managerErr: nil, + expectedCtx: state.ProcessingContext{ + BatchNumber: batchNum, + Coinbase: f.sequencerAddress, + Timestamp: now(), + GlobalExitRoot: oldHash, + }, + expectedErr: nil, + }, + { + name: "Manager Error", + batchNum: batchNum, + managerErr: testErr, + expectedCtx: state.ProcessingContext{}, + expectedErr: openBatchError, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + dbManagerMock.Mock.On("OpenBatch", mock.Anything, mock.Anything, mock.Anything).Return(tc.managerErr).Once() + + // act + actualCtx, err := f.openBatch(ctx, tc.batchNum, oldHash, nil) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + assert.ErrorIs(t, err, tc.managerErr) + assert.Empty(t, actualCtx) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedCtx, actualCtx) + } + dbManagerMock.AssertExpectations(t) + }) + } +} + +/* +// TestFinalizer_reprocessBatch is a test for reprocessBatch which tests all possible cases of reprocessBatch +func TestFinalizer_reprocessBatch(t *testing.T) { + // arrange + now = testNow + defer func() { + now = time.Now + }() + + f = setupFinalizer(true) + n := uint(2) + expectedProcessBatchRequest := state.ProcessRequest{ + BatchNumber: f.batch.batchNumber, + OldStateRoot: oldHash, + Coinbase: f.sequencerAddress, + Timestamp: f.batch.timestamp, + Caller: state.DiscardCallerLabel, + } + batches := []*state.Batch{ + { + BatchNumber: f.batch.batchNumber, + StateRoot: newHash, + Timestamp: testNow(), + }, + { + BatchNumber: f.batch.batchNumber - 1, + GlobalExitRoot: oldHash, + StateRoot: oldHash, + Timestamp: testNow(), + }, + } + + // TODO: Add missing cases for this test + testCases := []struct { + name string + getLastNBatchesErr error + processBatchErr error + batches []*state.Batch + expectedErr error + internalErr error + expectedProcessRequest state.ProcessRequest + expectedProcessBatchResult *state.ProcessBatchResponse + }{ + { + name: "Success", + batches: batches, + expectedProcessRequest: expectedProcessBatchRequest, + expectedProcessBatchResult: &state.ProcessBatchResponse{ + NewStateRoot: newHash, + IsBatchProcessed: true, + }, + }, + { + name: "GetLastNBatches Error", + getLastNBatchesErr: testErr, + internalErr: testErr, + expectedErr: fmt.Errorf("failed to get old state root, err: failed to get last %d batches, err: %w", n, testErr), + }, + { + name: "ProcessBatch Error", + processBatchErr: testErr, + internalErr: testErr, + expectedErr: testErr, + expectedProcessRequest: expectedProcessBatchRequest, + batches: batches, + }, + { + name: "ProcessBatch Result Error", + processBatchErr: testErr, + internalErr: testErr, + expectedProcessRequest: expectedProcessBatchRequest, + expectedErr: testErr, + batches: batches, + expectedProcessBatchResult: &state.ProcessBatchResponse{ + IsBatchProcessed: false, + ExecutorError: testErr2, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + f.processRequest = tc.expectedProcessRequest + dbManagerMock.On("GetLastNBatches", ctx, n).Return(tc.batches, tc.getLastNBatchesErr).Once() + if tc.getLastNBatchesErr == nil { + executorMock.Mock.On("ProcessBatch", ctx, f.processRequest, true).Return(tc.expectedProcessBatchResult, tc.processBatchErr).Once() + dbManagerMock.On("GetBatchByNumber", ctx, f.batch.batchNumber, nil).Return(tc.batches[0], nil).Once() + } + + // act + err := f.reprocessBatch(ctx, f.batch.batchNumber) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + assert.ErrorIs(t, err, tc.internalErr) + } else { + assert.NoError(t, err) + } + }) + } +} +*/ + +func TestFinalizer_isDeadlineEncountered(t *testing.T) { + // arrange + f = setupFinalizer(true) + now = testNow + defer func() { + now = time.Now + }() + testCases := []struct { + name string + nextForcedBatch int64 + nextGER int64 + nextDelayedBatch int64 + expected bool + }{ + { + name: "No deadlines", + nextForcedBatch: 0, + nextGER: 0, + nextDelayedBatch: 0, + expected: false, + }, + { + name: "Forced batch deadline", + nextForcedBatch: now().Add(time.Second).Unix(), + nextGER: 0, + nextDelayedBatch: 0, + expected: true, + }, + { + name: "Global Exit Root deadline", + nextForcedBatch: 0, + nextGER: now().Add(time.Second).Unix(), + nextDelayedBatch: 0, + expected: true, + }, + { + name: "Delayed batch deadline", + nextForcedBatch: 0, + nextGER: 0, + nextDelayedBatch: now().Add(time.Second).Unix(), + expected: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + f.nextForcedBatchDeadline = tc.nextForcedBatch + f.nextGERDeadline = tc.nextGER + if tc.expected == true { + now = func() time.Time { + return testNow().Add(time.Second * 2) + } + } + + // act + actual := f.isDeadlineEncountered() + + // assert + assert.Equal(t, tc.expected, actual) + }) + } +} + +func TestFinalizer_checkRemainingResources(t *testing.T) { + // arrange + f = setupFinalizer(true) + ctx := context.Background() + txResponse := &state.ProcessTransactionResponse{TxHash: oldHash} + result := &state.ProcessBatchResponse{ + UsedZkCounters: state.ZKCounters{CumulativeGasUsed: 1000}, + Responses: []*state.ProcessTransactionResponse{txResponse}, + } + remainingResources := state.BatchResources{ + ZKCounters: state.ZKCounters{CumulativeGasUsed: 9000}, + Bytes: 10000, + } + f.batch.remainingResources = remainingResources + testCases := []struct { + name string + remaining state.BatchResources + expectedErr error + expectedWorkerUpdate bool + expectedTxTracker *TxTracker + }{ + { + name: "Success", + remaining: remainingResources, + expectedErr: nil, + expectedWorkerUpdate: false, + expectedTxTracker: &TxTracker{RawTx: []byte("test")}, + }, + { + name: "Bytes Resource Exceeded", + remaining: state.BatchResources{ + Bytes: 0, + }, + expectedErr: state.ErrBatchResourceBytesUnderflow, + expectedWorkerUpdate: true, + expectedTxTracker: &TxTracker{RawTx: []byte("test")}, + }, + { + name: "ZkCounter Resource Exceeded", + remaining: state.BatchResources{ + ZKCounters: state.ZKCounters{CumulativeGasUsed: 0}, + }, + expectedErr: state.NewBatchRemainingResourcesUnderflowError(cumulativeGasErr, cumulativeGasErr.Error()), + expectedWorkerUpdate: true, + expectedTxTracker: &TxTracker{RawTx: make([]byte, 0)}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + f.batch.remainingResources = tc.remaining + dbManagerMock.On("AddEvent", ctx, mock.Anything, nil).Return(nil) + if tc.expectedWorkerUpdate { + workerMock.On("UpdateTx", txResponse.TxHash, tc.expectedTxTracker.From, result.UsedZkCounters).Return().Once() + } + + // act + err := f.checkRemainingResources(result, tc.expectedTxTracker) + + // assert + if tc.expectedErr != nil { + assert.Error(t, err) + assert.EqualError(t, err, tc.expectedErr.Error()) + } else { + assert.NoError(t, err) + } + if tc.expectedWorkerUpdate { + workerMock.AssertCalled(t, "UpdateTx", txResponse.TxHash, tc.expectedTxTracker.From, result.UsedZkCounters) + } else { + workerMock.AssertNotCalled(t, "UpdateTx", mock.Anything, mock.Anything, mock.Anything) + } + }) + } +} + +func TestFinalizer_isBatchReadyToClose(t *testing.T) { + // arrange + f = setupFinalizer(true) + maxRemainingResource := getMaxRemainingResources(bc) + testCases := []struct { + name string + cumulativeGasUsed uint64 + expectedResult bool + }{ + { + name: "Is ready", + cumulativeGasUsed: f.getConstraintThresholdUint64(bc.MaxCumulativeGasUsed) - 1, + expectedResult: true, + }, { + name: "Is NOT ready", + cumulativeGasUsed: f.getConstraintThresholdUint64(bc.MaxCumulativeGasUsed) + 1, + expectedResult: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + maxRemainingResource.ZKCounters.CumulativeGasUsed = tc.cumulativeGasUsed + f.batch.remainingResources = maxRemainingResource + // act + result := f.isBatchAlmostFull() + + // assert + assert.Equal(t, tc.expectedResult, result) + }) + } +} + +func TestFinalizer_setNextForcedBatchDeadline(t *testing.T) { + // arrange + f = setupFinalizer(false) + now = testNow + defer func() { + now = time.Now + }() + expected := now().Unix() + int64(f.cfg.ForcedBatchDeadlineTimeout.Duration.Seconds()) + + // act + f.setNextForcedBatchDeadline() + + // assert + assert.Equal(t, expected, f.nextForcedBatchDeadline) +} + +func TestFinalizer_setNextGERDeadline(t *testing.T) { + // arrange + f = setupFinalizer(false) + now = testNow + defer func() { + now = time.Now + }() + expected := now().Unix() + int64(f.cfg.GERDeadlineTimeout.Duration.Seconds()) + + // act + f.setNextGERDeadline() + + // assert + assert.Equal(t, expected, f.nextGERDeadline) +} + +func TestFinalizer_getConstraintThresholdUint64(t *testing.T) { + // arrange + f = setupFinalizer(false) + input := uint64(100) + expect := input * uint64(f.cfg.ResourcePercentageToCloseBatch) / 100 + + // act + result := f.getConstraintThresholdUint64(input) + + // assert + assert.Equal(t, result, expect) +} + +func TestFinalizer_getConstraintThresholdUint32(t *testing.T) { + // arrange + f = setupFinalizer(false) + input := uint32(100) + expect := uint32(input * f.cfg.ResourcePercentageToCloseBatch / 100) + + // act + result := f.getConstraintThresholdUint32(input) + + // assert + assert.Equal(t, result, expect) +} + +func TestFinalizer_getRemainingResources(t *testing.T) { + // act + remainingResources := getMaxRemainingResources(bc) + + // assert + assert.Equal(t, remainingResources.ZKCounters.CumulativeGasUsed, bc.MaxCumulativeGasUsed) + assert.Equal(t, remainingResources.ZKCounters.UsedKeccakHashes, bc.MaxKeccakHashes) + assert.Equal(t, remainingResources.ZKCounters.UsedPoseidonHashes, bc.MaxPoseidonHashes) + assert.Equal(t, remainingResources.ZKCounters.UsedPoseidonPaddings, bc.MaxPoseidonPaddings) + assert.Equal(t, remainingResources.ZKCounters.UsedMemAligns, bc.MaxMemAligns) + assert.Equal(t, remainingResources.ZKCounters.UsedArithmetics, bc.MaxArithmetics) + assert.Equal(t, remainingResources.ZKCounters.UsedBinaries, bc.MaxBinaries) + assert.Equal(t, remainingResources.ZKCounters.UsedSteps, bc.MaxSteps) + assert.Equal(t, remainingResources.Bytes, bc.MaxBatchBytesSize) +} + +func setupFinalizer(withWipBatch bool) *finalizer { + wipBatch := new(WipBatch) + dbManagerMock = new(DbManagerMock) + executorMock = new(StateMock) + workerMock = new(WorkerMock) + dbTxMock = new(DbTxMock) + if withWipBatch { + wipBatch = &WipBatch{ + batchNumber: 1, + coinbase: seqAddr, + initialStateRoot: oldHash, + stateRoot: newHash, + timestamp: now(), + globalExitRoot: oldHash, + remainingResources: getMaxRemainingResources(bc), + } + } + return &finalizer{ + cfg: cfg, + txsStore: txsStore, + closingSignalCh: closingSignalCh, + isSynced: isSynced, + sequencerAddress: seqAddr, + worker: workerMock, + dbManager: dbManagerMock, + executor: executorMock, + sharedResourcesMux: new(sync.RWMutex), + batch: wipBatch, + batchConstraints: bc, + processRequest: state.ProcessRequest{}, + // closing signals + nextGER: common.Hash{}, + nextGERDeadline: 0, + nextGERMux: new(sync.RWMutex), + nextForcedBatches: make([]state.ForcedBatch, 0), + nextForcedBatchDeadline: 0, + nextForcedBatchesMux: new(sync.RWMutex), + } +} + +func TestFinalizer_handleTransactionError(t *testing.T) { + // arrange + f = setupFinalizer(true) + nonce := uint64(0) + tx := &TxTracker{Hash: oldHash, From: sender, Cost: big.NewInt(0)} + testCases := []struct { + name string + error pb.RomError + expectedDeleteCall bool + updateTxStatus pool.TxStatus + expectedMoveCall bool + }{ + { + name: "OutOfCountersError", + error: pb.RomError(executor.ROM_ERROR_OUT_OF_COUNTERS_STEP), + updateTxStatus: pool.TxStatusInvalid, + expectedDeleteCall: true, + }, + { + name: "IntrinsicError", + error: pb.RomError(executor.ROM_ERROR_INTRINSIC_INVALID_NONCE), + updateTxStatus: pool.TxStatusFailed, + expectedMoveCall: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // arrange + if tc.expectedDeleteCall { + workerMock.On("DeleteTx", oldHash, sender).Return() + dbManagerMock.On("UpdateTxStatus", ctx, oldHash, tc.updateTxStatus, false, mock.Anything).Return(nil).Once() + dbManagerMock.On("DeleteTransactionFromPool", ctx, tx.Hash).Return(nil).Once() + } + if tc.expectedMoveCall { + workerMock.On("MoveTxToNotReady", oldHash, sender, &nonce, big.NewInt(0)).Return([]*TxTracker{}).Once() + } + + result := &state.ProcessBatchResponse{ + ReadWriteAddresses: map[common.Address]*state.InfoReadWrite{ + sender: {Nonce: &nonce, Balance: big.NewInt(0)}, + }, + Responses: []*state.ProcessTransactionResponse{{ + RomError: executor.RomErr(tc.error), + }, + }, + } + + // act + wg := f.handleProcessTransactionError(ctx, result, tx) + if wg != nil { + wg.Wait() + } + + // assert + workerMock.AssertExpectations(t) + }) + } +} diff --git a/sequencer/interfaces.go b/sequencer/interfaces.go index b6653b4173..c8122080a1 100644 --- a/sequencer/interfaces.go +++ b/sequencer/interfaces.go @@ -6,8 +6,11 @@ import ( "time" ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" + pb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" @@ -17,68 +20,108 @@ import ( // txPool contains the methods required to interact with the tx pool. type txPool interface { - GetPendingTxs(ctx context.Context, isClaims bool, limit uint64) ([]pool.Transaction, error) - UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus) error - UpdateTxsStatus(ctx context.Context, hashes []string, newStatus pool.TxStatus) error - IsTxPending(ctx context.Context, hash common.Hash) (bool, error) - DeleteTxsByHashes(ctx context.Context, hashes []common.Hash) error - MarkReorgedTxsAsPending(ctx context.Context) error - GetTxs(ctx context.Context, filterStatus pool.TxStatus, isClaims bool, minGasPrice, limit uint64) ([]*pool.Transaction, error) - GetTxFromAddressFromByHash(ctx context.Context, hash common.Hash) (common.Address, uint64, error) - IncrementFailedCounter(ctx context.Context, hashes []string) error + DeleteTransactionsByHashes(ctx context.Context, hashes []common.Hash) error + DeleteTransactionByHash(ctx context.Context, hash common.Hash) error + MarkWIPTxsAsPending(ctx context.Context) error + GetNonWIPPendingTxs(ctx context.Context, limit uint64) ([]pool.Transaction, error) + UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus, isWIP bool, failedReason *string) error + GetTxZkCountersByHash(ctx context.Context, hash common.Hash) (*state.ZKCounters, error) + UpdateTxWIPStatus(ctx context.Context, hash common.Hash, isWIP bool) error } // etherman contains the methods required to interact with ethereum. type etherman interface { - EstimateGasSequenceBatches(sequences []ethmanTypes.Sequence) (*types.Transaction, error) - GetSendSequenceFee() (*big.Int, error) + EstimateGasSequenceBatches(sender common.Address, sequences []ethmanTypes.Sequence) (*types.Transaction, error) + GetSendSequenceFee(numBatches uint64) (*big.Int, error) TrustedSequencer() (common.Address, error) GetLatestBatchNumber() (uint64, error) - GetLatestBlockNumber(ctx context.Context) (uint64, error) GetLastBatchTimestamp() (uint64, error) GetLatestBlockTimestamp(ctx context.Context) (uint64, error) + BuildSequenceBatchesTxData(sender common.Address, sequences []ethmanTypes.Sequence) (to *common.Address, data []byte, err error) + GetLatestBlockNumber(ctx context.Context) (uint64, error) } // stateInterface gathers the methods required to interact with the state. type stateInterface interface { - GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) - GetLatestGlobalExitRoot(ctx context.Context, dbTx pgx.Tx) (*state.GlobalExitRoot, error) GetTimeForLatestBatchVirtualization(ctx context.Context, dbTx pgx.Tx) (time.Time, error) GetTxsOlderThanNL1Blocks(ctx context.Context, nL1Blocks uint64, dbTx pgx.Tx) ([]common.Hash, error) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (txs []types.Transaction, err error) + BeginStateTransaction(ctx context.Context) (pgx.Tx, error) + GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) IsBatchClosed(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (bool, error) - IsBatchVirtualized(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (bool, error) - + Begin(ctx context.Context) (pgx.Tx, error) + GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) + GetNonceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) + GetLastStateRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) + ProcessBatch(ctx context.Context, request state.ProcessRequest, updateMerkleTree bool) (*state.ProcessBatchResponse, error) + CloseBatch(ctx context.Context, receipt state.ProcessingReceipt, dbTx pgx.Tx) error + ExecuteBatch(ctx context.Context, batch state.Batch, updateMerkleTree bool, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) + GetForcedBatch(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (*state.ForcedBatch, error) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) - - StoreTransactions(ctx context.Context, batchNum uint64, processedTxs []*state.ProcessTransactionResponse, dbTx pgx.Tx) error - CloseBatch(ctx context.Context, receipt state.ProcessingReceipt, dbTx pgx.Tx) error OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error - ProcessSequencerBatch(ctx context.Context, batchNumber uint64, txs []types.Transaction, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) - - UpdateGERInOpenBatch(ctx context.Context, ger common.Hash, dbTx pgx.Tx) error - GetBlockNumAndMainnetExitRootByGER(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (uint64, common.Hash, error) - GetStateRootByBatchNumber(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (common.Hash, error) - - BeginStateTransaction(ctx context.Context) (pgx.Tx, error) - - GetNonce(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (uint64, error) - GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLastNBatches(ctx context.Context, numBatches uint, dbTx pgx.Tx) ([]*state.Batch, error) + StoreTransaction(ctx context.Context, batchNumber uint64, processedTx *state.ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error + GetLastClosedBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) + GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) + GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) + GetLatestGlobalExitRoot(ctx context.Context, maxBlockNumber uint64, dbTx pgx.Tx) (state.GlobalExitRoot, time.Time, error) + GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) + UpdateBatchL2Data(ctx context.Context, batchNumber uint64, batchL2Data []byte, dbTx pgx.Tx) error + ProcessSequencerBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) + GetForcedBatchesSince(ctx context.Context, forcedBatchNumber, maxBlockNumber uint64, dbTx pgx.Tx) ([]*state.ForcedBatch, error) + GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) + CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetLatestGer(ctx context.Context, maxBlockNumber uint64) (state.GlobalExitRoot, time.Time, error) + FlushMerkleTree(ctx context.Context) error } -type txManager interface { - SequenceBatches(sequences []ethmanTypes.Sequence) +type workerInterface interface { + GetBestFittingTx(resources state.BatchResources) *TxTracker + UpdateAfterSingleSuccessfulTxExecution(from common.Address, touchedAddresses map[common.Address]*state.InfoReadWrite) []*TxTracker + UpdateTx(txHash common.Hash, from common.Address, ZKCounters state.ZKCounters) + AddTxTracker(ctx context.Context, txTracker *TxTracker) (dropReason error, isWIP bool) + MoveTxToNotReady(txHash common.Hash, from common.Address, actualNonce *uint64, actualBalance *big.Int) []*TxTracker + DeleteTx(txHash common.Hash, from common.Address) + HandleL2Reorg(txHashes []common.Hash) + NewTxTracker(tx types.Transaction, counters state.ZKCounters, ip string) (*TxTracker, error) } -// priceGetter is for getting eth/matic price, used for the tx profitability checker -type priceGetter interface { - Start(ctx context.Context) - GetEthToMaticPrice(ctx context.Context) (*big.Float, error) +// The dbManager will need to handle the errors inside the functions which don't return error as they will be used async in the other abstractions. +// Also if dbTx is missing this needs also to be handled in the dbManager +type dbManagerInterface interface { + OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error + BeginStateTransaction(ctx context.Context) (pgx.Tx, error) + CreateFirstBatch(ctx context.Context, sequencerAddress common.Address) state.ProcessingContext + GetLastBatchNumber(ctx context.Context) (uint64, error) + StoreProcessedTransaction(ctx context.Context, batchNumber uint64, processedTx *state.ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error + DeleteTransactionFromPool(ctx context.Context, txHash common.Hash) error + CloseBatch(ctx context.Context, params ClosingBatchParameters) error + GetWIPBatch(ctx context.Context) (*WipBatch, error) + GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64) (txs []types.Transaction, err error) + GetLastBatch(ctx context.Context) (*state.Batch, error) + GetLastNBatches(ctx context.Context, numBatches uint) ([]*state.Batch, error) + GetLastClosedBatch(ctx context.Context) (*state.Batch, error) + GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + IsBatchClosed(ctx context.Context, batchNum uint64) (bool, error) + GetLatestGer(ctx context.Context, maxBlockNumber uint64) (state.GlobalExitRoot, time.Time, error) + ProcessForcedBatch(ForcedBatchNumber uint64, request state.ProcessRequest) (*state.ProcessBatchResponse, error) + GetForcedBatchesSince(ctx context.Context, forcedBatchNumber, maxBlockNumber uint64, dbTx pgx.Tx) ([]*state.ForcedBatch, error) + GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) + GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) + GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) + GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) + UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus, isWIP bool, reason *string) error + GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) + CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) + FlushMerkleTree(ctx context.Context) error } -// gasPriceEstimator contains the methods required to interact with gas price estimator -type gasPriceEstimator interface { - GetAvgGasPrice(ctx context.Context) (*big.Int, error) +type ethTxManager interface { + Add(ctx context.Context, owner, id string, from common.Address, to *common.Address, value *big.Int, data []byte, dbTx pgx.Tx) error + Result(ctx context.Context, owner, id string, dbTx pgx.Tx) (ethtxmanager.MonitoredTxResult, error) + ResultsByStatus(ctx context.Context, owner string, statuses []ethtxmanager.MonitoredTxStatus, dbTx pgx.Tx) ([]ethtxmanager.MonitoredTxResult, error) + ProcessPendingMonitoredTxs(ctx context.Context, owner string, failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) } diff --git a/sequencer/metrics/metrics.go b/sequencer/metrics/metrics.go new file mode 100644 index 0000000000..df82049a99 --- /dev/null +++ b/sequencer/metrics/metrics.go @@ -0,0 +1,153 @@ +package metrics + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + // Prefix for the metrics of the sequencer package. + Prefix = "sequencer_" + // SequencesSentToL1CountName is the name of the metric that counts the sequences sent to L1. + SequencesSentToL1CountName = Prefix + "sequences_sent_to_L1_count" + // GasPriceEstimatedAverageName is the name of the metric that shows the average estimated gas price. + GasPriceEstimatedAverageName = Prefix + "gas_price_estimated_average" + // TxProcessedName is the name of the metric that counts the processed transactions. + TxProcessedName = Prefix + "transaction_processed" + // SequencesOversizedDataErrorName is the name of the metric that counts the sequences with oversized data error. + SequencesOversizedDataErrorName = Prefix + "sequences_oversized_data_error" + // EthToMaticPriceName is the name of the metric that shows the Ethereum to Matic price. + EthToMaticPriceName = Prefix + "eth_to_matic_price" + // SequenceRewardInMaticName is the name of the metric that shows the reward in Matic of a sequence. + SequenceRewardInMaticName = Prefix + "sequence_reward_in_matic" + // ProcessingTimeName is the name of the metric that shows the processing time. + ProcessingTimeName = Prefix + "processing_time" + // WorkerPrefix is the prefix for the metrics of the worker. + WorkerPrefix = Prefix + "worker_" + // WorkerProcessingTimeName is the name of the metric that shows the worker processing time. + WorkerProcessingTimeName = WorkerPrefix + "processing_time" + // TxProcessedLabelName is the name of the label for the processed transactions. + TxProcessedLabelName = "status" +) + +// TxProcessedLabel represents the possible values for the +// `sequencer_transaction_processed` metric `type` label. +type TxProcessedLabel string + +const ( + // TxProcessedLabelSuccessful represents a successful transaction + TxProcessedLabelSuccessful TxProcessedLabel = "successful" + // TxProcessedLabelInvalid represents an invalid transaction + TxProcessedLabelInvalid TxProcessedLabel = "invalid" + // TxProcessedLabelFailed represents a failed transaction + TxProcessedLabelFailed TxProcessedLabel = "failed" +) + +// Register the metrics for the sequencer package. +func Register() { + var ( + counters []prometheus.CounterOpts + counterVecs []metrics.CounterVecOpts + gauges []prometheus.GaugeOpts + histograms []prometheus.HistogramOpts + ) + + counters = []prometheus.CounterOpts{ + { + Name: SequencesSentToL1CountName, + Help: "[SEQUENCER] total count of sequences sent to L1", + }, + { + Name: SequencesOversizedDataErrorName, + Help: "[SEQUENCER] total count of sequences with oversized data error", + }, + } + + counterVecs = []metrics.CounterVecOpts{ + { + CounterOpts: prometheus.CounterOpts{ + Name: TxProcessedName, + Help: "[SEQUENCER] number of transactions processed", + }, + Labels: []string{TxProcessedLabelName}, + }, + } + + gauges = []prometheus.GaugeOpts{ + { + Name: GasPriceEstimatedAverageName, + Help: "[SEQUENCER] average gas price estimated", + }, + { + Name: EthToMaticPriceName, + Help: "[SEQUENCER] eth to matic price", + }, + { + Name: SequenceRewardInMaticName, + Help: "[SEQUENCER] reward for a sequence in Matic", + }, + } + + histograms = []prometheus.HistogramOpts{ + { + Name: ProcessingTimeName, + Help: "[SEQUENCER] processing time", + }, + { + Name: WorkerProcessingTimeName, + Help: "[SEQUENCER] worker processing time", + }, + } + + metrics.RegisterCounters(counters...) + metrics.RegisterCounterVecs(counterVecs...) + metrics.RegisterGauges(gauges...) + metrics.RegisterHistograms(histograms...) +} + +// AverageGasPrice sets the gauge to the given average gas price. +func AverageGasPrice(price float64) { + metrics.GaugeSet(GasPriceEstimatedAverageName, price) +} + +// SequencesSentToL1 increases the counter by the provided number of sequences +// sent to L1. +func SequencesSentToL1(numSequences float64) { + metrics.CounterAdd(SequencesSentToL1CountName, numSequences) +} + +// TxProcessed increases the counter vector by the provided transactions count +// and for the given label. +func TxProcessed(status TxProcessedLabel, count float64) { + metrics.CounterVecAdd(TxProcessedName, string(status), count) +} + +// SequencesOvesizedDataError increases the counter for sequences that +// encounter a OversizedData error. +func SequencesOvesizedDataError() { + metrics.CounterInc(SequencesOversizedDataErrorName) +} + +// EthToMaticPrice sets the gauge for the Ethereum to Matic price. +func EthToMaticPrice(price float64) { + metrics.GaugeSet(EthToMaticPriceName, price) +} + +// SequenceRewardInMatic sets the gauge for the reward in Matic of a sequence. +func SequenceRewardInMatic(reward float64) { + metrics.GaugeSet(SequenceRewardInMaticName, reward) +} + +// ProcessingTime observes the last processing time on the histogram. +func ProcessingTime(lastProcessTime time.Duration) { + execTimeInSeconds := float64(lastProcessTime) / float64(time.Second) + metrics.HistogramObserve(ProcessingTimeName, execTimeInSeconds) +} + +// WorkerProcessingTime observes the last processing time on the histogram. +func WorkerProcessingTime(lastProcessTime time.Duration) { + execTimeInSeconds := float64(lastProcessTime) / float64(time.Second) + metrics.HistogramObserve(WorkerProcessingTimeName, execTimeInSeconds) +} diff --git a/sequencer/mock_db_manager.go b/sequencer/mock_db_manager.go new file mode 100644 index 0000000000..7f30bc1a11 --- /dev/null +++ b/sequencer/mock_db_manager.go @@ -0,0 +1,603 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package sequencer + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" + + pool "github.com/0xPolygonHermez/zkevm-node/pool" + + state "github.com/0xPolygonHermez/zkevm-node/state" + + time "time" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// DbManagerMock is an autogenerated mock type for the dbManagerInterface type +type DbManagerMock struct { + mock.Mock +} + +// BeginStateTransaction provides a mock function with given fields: ctx +func (_m *DbManagerMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CloseBatch provides a mock function with given fields: ctx, params +func (_m *DbManagerMock) CloseBatch(ctx context.Context, params ClosingBatchParameters) error { + ret := _m.Called(ctx, params) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, ClosingBatchParameters) error); ok { + r0 = rf(ctx, params) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CountReorgs provides a mock function with given fields: ctx, dbTx +func (_m *DbManagerMock) CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateFirstBatch provides a mock function with given fields: ctx, sequencerAddress +func (_m *DbManagerMock) CreateFirstBatch(ctx context.Context, sequencerAddress common.Address) state.ProcessingContext { + ret := _m.Called(ctx, sequencerAddress) + + var r0 state.ProcessingContext + if rf, ok := ret.Get(0).(func(context.Context, common.Address) state.ProcessingContext); ok { + r0 = rf(ctx, sequencerAddress) + } else { + r0 = ret.Get(0).(state.ProcessingContext) + } + + return r0 +} + +// DeleteTransactionFromPool provides a mock function with given fields: ctx, txHash +func (_m *DbManagerMock) DeleteTransactionFromPool(ctx context.Context, txHash common.Hash) error { + ret := _m.Called(ctx, txHash) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) error); ok { + r0 = rf(ctx, txHash) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// FlushMerkleTree provides a mock function with given fields: ctx +func (_m *DbManagerMock) FlushMerkleTree(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetBalanceByStateRoot provides a mock function with given fields: ctx, address, root +func (_m *DbManagerMock) GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + ret := _m.Called(ctx, address, root) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) (*big.Int, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) *big.Int); ok { + r0 = rf(ctx, address, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *DbManagerMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetForcedBatchesSince provides a mock function with given fields: ctx, forcedBatchNumber, maxBlockNumber, dbTx +func (_m *DbManagerMock) GetForcedBatchesSince(ctx context.Context, forcedBatchNumber uint64, maxBlockNumber uint64, dbTx pgx.Tx) ([]*state.ForcedBatch, error) { + ret := _m.Called(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + + var r0 []*state.ForcedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) ([]*state.ForcedBatch, error)); ok { + return rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) []*state.ForcedBatch); ok { + r0 = rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*state.ForcedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBatch provides a mock function with given fields: ctx +func (_m *DbManagerMock) GetLastBatch(ctx context.Context) (*state.Batch, error) { + ret := _m.Called(ctx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*state.Batch, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *state.Batch); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBatchNumber provides a mock function with given fields: ctx +func (_m *DbManagerMock) GetLastBatchNumber(ctx context.Context) (uint64, error) { + ret := _m.Called(ctx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBlock provides a mock function with given fields: ctx, dbTx +func (_m *DbManagerMock) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Block, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Block); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastClosedBatch provides a mock function with given fields: ctx +func (_m *DbManagerMock) GetLastClosedBatch(ctx context.Context) (*state.Batch, error) { + ret := _m.Called(ctx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*state.Batch, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *state.Batch); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastL2BlockHeader provides a mock function with given fields: ctx, dbTx +func (_m *DbManagerMock) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*types.Header, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *types.Header); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Header) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastNBatches provides a mock function with given fields: ctx, numBatches +func (_m *DbManagerMock) GetLastNBatches(ctx context.Context, numBatches uint) ([]*state.Batch, error) { + ret := _m.Called(ctx, numBatches) + + var r0 []*state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint) ([]*state.Batch, error)); ok { + return rf(ctx, numBatches) + } + if rf, ok := ret.Get(0).(func(context.Context, uint) []*state.Batch); ok { + r0 = rf(ctx, numBatches) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok { + r1 = rf(ctx, numBatches) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastTrustedForcedBatchNumber provides a mock function with given fields: ctx, dbTx +func (_m *DbManagerMock) GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLatestGer provides a mock function with given fields: ctx, maxBlockNumber +func (_m *DbManagerMock) GetLatestGer(ctx context.Context, maxBlockNumber uint64) (state.GlobalExitRoot, time.Time, error) { + ret := _m.Called(ctx, maxBlockNumber) + + var r0 state.GlobalExitRoot + var r1 time.Time + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (state.GlobalExitRoot, time.Time, error)); ok { + return rf(ctx, maxBlockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) state.GlobalExitRoot); ok { + r0 = rf(ctx, maxBlockNumber) + } else { + r0 = ret.Get(0).(state.GlobalExitRoot) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) time.Time); ok { + r1 = rf(ctx, maxBlockNumber) + } else { + r1 = ret.Get(1).(time.Time) + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64) error); ok { + r2 = rf(ctx, maxBlockNumber) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetLatestVirtualBatchTimestamp provides a mock function with given fields: ctx, dbTx +func (_m *DbManagerMock) GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { + ret := _m.Called(ctx, dbTx) + + var r0 time.Time + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (time.Time, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) time.Time); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(time.Time) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionsByBatchNumber provides a mock function with given fields: ctx, batchNumber +func (_m *DbManagerMock) GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64) ([]types.Transaction, error) { + ret := _m.Called(ctx, batchNumber) + + var r0 []types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]types.Transaction, error)); ok { + return rf(ctx, batchNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []types.Transaction); ok { + r0 = rf(ctx, batchNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, batchNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetWIPBatch provides a mock function with given fields: ctx +func (_m *DbManagerMock) GetWIPBatch(ctx context.Context) (*WipBatch, error) { + ret := _m.Called(ctx) + + var r0 *WipBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*WipBatch, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *WipBatch); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*WipBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IsBatchClosed provides a mock function with given fields: ctx, batchNum +func (_m *DbManagerMock) IsBatchClosed(ctx context.Context, batchNum uint64) (bool, error) { + ret := _m.Called(ctx, batchNum) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (bool, error)); ok { + return rf(ctx, batchNum) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) bool); ok { + r0 = rf(ctx, batchNum) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, batchNum) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// OpenBatch provides a mock function with given fields: ctx, processingContext, dbTx +func (_m *DbManagerMock) OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error { + ret := _m.Called(ctx, processingContext, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingContext, pgx.Tx) error); ok { + r0 = rf(ctx, processingContext, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ProcessForcedBatch provides a mock function with given fields: ForcedBatchNumber, request +func (_m *DbManagerMock) ProcessForcedBatch(ForcedBatchNumber uint64, request state.ProcessRequest) (*state.ProcessBatchResponse, error) { + ret := _m.Called(ForcedBatchNumber, request) + + var r0 *state.ProcessBatchResponse + var r1 error + if rf, ok := ret.Get(0).(func(uint64, state.ProcessRequest) (*state.ProcessBatchResponse, error)); ok { + return rf(ForcedBatchNumber, request) + } + if rf, ok := ret.Get(0).(func(uint64, state.ProcessRequest) *state.ProcessBatchResponse); ok { + r0 = rf(ForcedBatchNumber, request) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.ProcessBatchResponse) + } + } + + if rf, ok := ret.Get(1).(func(uint64, state.ProcessRequest) error); ok { + r1 = rf(ForcedBatchNumber, request) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StoreProcessedTransaction provides a mock function with given fields: ctx, batchNumber, processedTx, coinbase, timestamp, dbTx +func (_m *DbManagerMock) StoreProcessedTransaction(ctx context.Context, batchNumber uint64, processedTx *state.ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, processedTx, coinbase, timestamp, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *state.ProcessTransactionResponse, common.Address, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, processedTx, coinbase, timestamp, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateTxStatus provides a mock function with given fields: ctx, hash, newStatus, isWIP, reason +func (_m *DbManagerMock) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus, isWIP bool, reason *string) error { + ret := _m.Called(ctx, hash, newStatus, isWIP, reason) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pool.TxStatus, bool, *string) error); ok { + r0 = rf(ctx, hash, newStatus, isWIP, reason) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewDbManagerMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewDbManagerMock creates a new instance of DbManagerMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewDbManagerMock(t mockConstructorTestingTNewDbManagerMock) *DbManagerMock { + mock := &DbManagerMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencer/mock_dbtx.go b/sequencer/mock_dbtx.go new file mode 100644 index 0000000000..196f2b1850 --- /dev/null +++ b/sequencer/mock_dbtx.go @@ -0,0 +1,299 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package sequencer + +import ( + context "context" + + pgconn "github.com/jackc/pgconn" + mock "github.com/stretchr/testify/mock" + + pgx "github.com/jackc/pgx/v4" +) + +// DbTxMock is an autogenerated mock type for the Tx type +type DbTxMock struct { + mock.Mock +} + +// Begin provides a mock function with given fields: ctx +func (_m *DbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeginFunc provides a mock function with given fields: ctx, f +func (_m *DbTxMock) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { + ret := _m.Called(ctx, f) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, func(pgx.Tx) error) error); ok { + r0 = rf(ctx, f) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Commit provides a mock function with given fields: ctx +func (_m *DbTxMock) Commit(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Conn provides a mock function with given fields: +func (_m *DbTxMock) Conn() *pgx.Conn { + ret := _m.Called() + + var r0 *pgx.Conn + if rf, ok := ret.Get(0).(func() *pgx.Conn); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pgx.Conn) + } + } + + return r0 +} + +// CopyFrom provides a mock function with given fields: ctx, tableName, columnNames, rowSrc +func (_m *DbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { + ret := _m.Called(ctx, tableName, columnNames, rowSrc) + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)); ok { + return rf(ctx, tableName, columnNames, rowSrc) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) int64); ok { + r0 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) error); ok { + r1 = rf(ctx, tableName, columnNames, rowSrc) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Exec provides a mock function with given fields: ctx, sql, arguments +func (_m *DbTxMock) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error) { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, arguments...) + ret := _m.Called(_ca...) + + var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, arguments...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgconn.CommandTag); ok { + r0 = rf(ctx, sql, arguments...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgconn.CommandTag) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(ctx, sql, arguments...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// LargeObjects provides a mock function with given fields: +func (_m *DbTxMock) LargeObjects() pgx.LargeObjects { + ret := _m.Called() + + var r0 pgx.LargeObjects + if rf, ok := ret.Get(0).(func() pgx.LargeObjects); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(pgx.LargeObjects) + } + + return r0 +} + +// Prepare provides a mock function with given fields: ctx, name, sql +func (_m *DbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgconn.StatementDescription, error) { + ret := _m.Called(ctx, name, sql) + + var r0 *pgconn.StatementDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*pgconn.StatementDescription, error)); ok { + return rf(ctx, name, sql) + } + if rf, ok := ret.Get(0).(func(context.Context, string, string) *pgconn.StatementDescription); ok { + r0 = rf(ctx, name, sql) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pgconn.StatementDescription) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { + r1 = rf(ctx, name, sql) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Query provides a mock function with given fields: ctx, sql, args +func (_m *DbTxMock) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error) { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 pgx.Rows + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgx.Rows, error)); ok { + return rf(ctx, sql, args...) + } + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Rows); ok { + r0 = rf(ctx, sql, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Rows) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { + r1 = rf(ctx, sql, args...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// QueryFunc provides a mock function with given fields: ctx, sql, args, scans, f +func (_m *DbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error) { + ret := _m.Called(ctx, sql, args, scans, f) + + var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, args, scans, f) + } + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) pgconn.CommandTag); ok { + r0 = rf(ctx, sql, args, scans, f) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgconn.CommandTag) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) error); ok { + r1 = rf(ctx, sql, args, scans, f) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// QueryRow provides a mock function with given fields: ctx, sql, args +func (_m *DbTxMock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row { + var _ca []interface{} + _ca = append(_ca, ctx, sql) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + var r0 pgx.Row + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Row); ok { + r0 = rf(ctx, sql, args...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Row) + } + } + + return r0 +} + +// Rollback provides a mock function with given fields: ctx +func (_m *DbTxMock) Rollback(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SendBatch provides a mock function with given fields: ctx, b +func (_m *DbTxMock) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { + ret := _m.Called(ctx, b) + + var r0 pgx.BatchResults + if rf, ok := ret.Get(0).(func(context.Context, *pgx.Batch) pgx.BatchResults); ok { + r0 = rf(ctx, b) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.BatchResults) + } + } + + return r0 +} + +type mockConstructorTestingTNewDbTxMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewDbTxMock creates a new instance of DbTxMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewDbTxMock(t mockConstructorTestingTNewDbTxMock) *DbTxMock { + mock := &DbTxMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencer/mocks/mock_etherman.go b/sequencer/mock_etherman.go similarity index 58% rename from sequencer/mocks/mock_etherman.go rename to sequencer/mock_etherman.go index d9a3105d7d..1089528dfa 100644 --- a/sequencer/mocks/mock_etherman.go +++ b/sequencer/mock_etherman.go @@ -1,6 +1,6 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. -package mocks +package sequencer import ( context "context" @@ -20,22 +20,60 @@ type EthermanMock struct { mock.Mock } -// EstimateGasSequenceBatches provides a mock function with given fields: sequences -func (_m *EthermanMock) EstimateGasSequenceBatches(sequences []types.Sequence) (*coretypes.Transaction, error) { - ret := _m.Called(sequences) +// BuildSequenceBatchesTxData provides a mock function with given fields: sender, sequences +func (_m *EthermanMock) BuildSequenceBatchesTxData(sender common.Address, sequences []types.Sequence) (*common.Address, []byte, error) { + ret := _m.Called(sender, sequences) + + var r0 *common.Address + var r1 []byte + var r2 error + if rf, ok := ret.Get(0).(func(common.Address, []types.Sequence) (*common.Address, []byte, error)); ok { + return rf(sender, sequences) + } + if rf, ok := ret.Get(0).(func(common.Address, []types.Sequence) *common.Address); ok { + r0 = rf(sender, sequences) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*common.Address) + } + } + + if rf, ok := ret.Get(1).(func(common.Address, []types.Sequence) []byte); ok { + r1 = rf(sender, sequences) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).([]byte) + } + } + + if rf, ok := ret.Get(2).(func(common.Address, []types.Sequence) error); ok { + r2 = rf(sender, sequences) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// EstimateGasSequenceBatches provides a mock function with given fields: sender, sequences +func (_m *EthermanMock) EstimateGasSequenceBatches(sender common.Address, sequences []types.Sequence) (*coretypes.Transaction, error) { + ret := _m.Called(sender, sequences) var r0 *coretypes.Transaction - if rf, ok := ret.Get(0).(func([]types.Sequence) *coretypes.Transaction); ok { - r0 = rf(sequences) + var r1 error + if rf, ok := ret.Get(0).(func(common.Address, []types.Sequence) (*coretypes.Transaction, error)); ok { + return rf(sender, sequences) + } + if rf, ok := ret.Get(0).(func(common.Address, []types.Sequence) *coretypes.Transaction); ok { + r0 = rf(sender, sequences) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*coretypes.Transaction) } } - var r1 error - if rf, ok := ret.Get(1).(func([]types.Sequence) error); ok { - r1 = rf(sequences) + if rf, ok := ret.Get(1).(func(common.Address, []types.Sequence) error); ok { + r1 = rf(sender, sequences) } else { r1 = ret.Error(1) } @@ -48,13 +86,16 @@ func (_m *EthermanMock) GetLastBatchTimestamp() (uint64, error) { ret := _m.Called() var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func() (uint64, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() uint64); ok { r0 = rf() } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -69,13 +110,16 @@ func (_m *EthermanMock) GetLatestBatchNumber() (uint64, error) { ret := _m.Called() var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func() (uint64, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() uint64); ok { r0 = rf() } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -90,13 +134,16 @@ func (_m *EthermanMock) GetLatestBlockNumber(ctx context.Context) (uint64, error ret := _m.Called(ctx) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { r0 = rf(ctx) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -111,13 +158,16 @@ func (_m *EthermanMock) GetLatestBlockTimestamp(ctx context.Context) (uint64, er ret := _m.Called(ctx) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { r0 = rf(ctx) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -127,22 +177,25 @@ func (_m *EthermanMock) GetLatestBlockTimestamp(ctx context.Context) (uint64, er return r0, r1 } -// GetSendSequenceFee provides a mock function with given fields: -func (_m *EthermanMock) GetSendSequenceFee() (*big.Int, error) { - ret := _m.Called() +// GetSendSequenceFee provides a mock function with given fields: numBatches +func (_m *EthermanMock) GetSendSequenceFee(numBatches uint64) (*big.Int, error) { + ret := _m.Called(numBatches) var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() + var r1 error + if rf, ok := ret.Get(0).(func(uint64) (*big.Int, error)); ok { + return rf(numBatches) + } + if rf, ok := ret.Get(0).(func(uint64) *big.Int); ok { + r0 = rf(numBatches) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(uint64) error); ok { + r1 = rf(numBatches) } else { r1 = ret.Error(1) } @@ -155,6 +208,10 @@ func (_m *EthermanMock) TrustedSequencer() (common.Address, error) { ret := _m.Called() var r0 common.Address + var r1 error + if rf, ok := ret.Get(0).(func() (common.Address, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() common.Address); ok { r0 = rf() } else { @@ -163,7 +220,6 @@ func (_m *EthermanMock) TrustedSequencer() (common.Address, error) { } } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { diff --git a/sequencer/mock_pool.go b/sequencer/mock_pool.go new file mode 100644 index 0000000000..5e9790839e --- /dev/null +++ b/sequencer/mock_pool.go @@ -0,0 +1,157 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package sequencer + +import ( + context "context" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + pool "github.com/0xPolygonHermez/zkevm-node/pool" + + state "github.com/0xPolygonHermez/zkevm-node/state" +) + +// PoolMock is an autogenerated mock type for the txPool type +type PoolMock struct { + mock.Mock +} + +// DeleteTransactionByHash provides a mock function with given fields: ctx, hash +func (_m *PoolMock) DeleteTransactionByHash(ctx context.Context, hash common.Hash) error { + ret := _m.Called(ctx, hash) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) error); ok { + r0 = rf(ctx, hash) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteTransactionsByHashes provides a mock function with given fields: ctx, hashes +func (_m *PoolMock) DeleteTransactionsByHashes(ctx context.Context, hashes []common.Hash) error { + ret := _m.Called(ctx, hashes) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []common.Hash) error); ok { + r0 = rf(ctx, hashes) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetNonWIPPendingTxs provides a mock function with given fields: ctx, limit +func (_m *PoolMock) GetNonWIPPendingTxs(ctx context.Context, limit uint64) ([]pool.Transaction, error) { + ret := _m.Called(ctx, limit) + + var r0 []pool.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]pool.Transaction, error)); ok { + return rf(ctx, limit) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []pool.Transaction); ok { + r0 = rf(ctx, limit) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]pool.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, limit) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTxZkCountersByHash provides a mock function with given fields: ctx, hash +func (_m *PoolMock) GetTxZkCountersByHash(ctx context.Context, hash common.Hash) (*state.ZKCounters, error) { + ret := _m.Called(ctx, hash) + + var r0 *state.ZKCounters + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) (*state.ZKCounters, error)); ok { + return rf(ctx, hash) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Hash) *state.ZKCounters); ok { + r0 = rf(ctx, hash) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.ZKCounters) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Hash) error); ok { + r1 = rf(ctx, hash) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MarkWIPTxsAsPending provides a mock function with given fields: ctx +func (_m *PoolMock) MarkWIPTxsAsPending(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateTxStatus provides a mock function with given fields: ctx, hash, newStatus, isWIP, failedReason +func (_m *PoolMock) UpdateTxStatus(ctx context.Context, hash common.Hash, newStatus pool.TxStatus, isWIP bool, failedReason *string) error { + ret := _m.Called(ctx, hash, newStatus, isWIP, failedReason) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, pool.TxStatus, bool, *string) error); ok { + r0 = rf(ctx, hash, newStatus, isWIP, failedReason) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateTxWIPStatus provides a mock function with given fields: ctx, hash, isWIP +func (_m *PoolMock) UpdateTxWIPStatus(ctx context.Context, hash common.Hash, isWIP bool) error { + ret := _m.Called(ctx, hash, isWIP) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, common.Hash, bool) error); ok { + r0 = rf(ctx, hash, isWIP) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewPoolMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewPoolMock creates a new instance of PoolMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewPoolMock(t mockConstructorTestingTNewPoolMock) *PoolMock { + mock := &PoolMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencer/mock_state.go b/sequencer/mock_state.go new file mode 100644 index 0000000000..1cbfdef53b --- /dev/null +++ b/sequencer/mock_state.go @@ -0,0 +1,838 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package sequencer + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + metrics "github.com/0xPolygonHermez/zkevm-node/state/metrics" + + mock "github.com/stretchr/testify/mock" + + pb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + + pgx "github.com/jackc/pgx/v4" + + state "github.com/0xPolygonHermez/zkevm-node/state" + + time "time" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// StateMock is an autogenerated mock type for the stateInterface type +type StateMock struct { + mock.Mock +} + +// Begin provides a mock function with given fields: ctx +func (_m *StateMock) Begin(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeginStateTransaction provides a mock function with given fields: ctx +func (_m *StateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { + ret := _m.Called(ctx) + + var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(pgx.Tx) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CloseBatch provides a mock function with given fields: ctx, receipt, dbTx +func (_m *StateMock) CloseBatch(ctx context.Context, receipt state.ProcessingReceipt, dbTx pgx.Tx) error { + ret := _m.Called(ctx, receipt, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingReceipt, pgx.Tx) error); ok { + r0 = rf(ctx, receipt, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CountReorgs provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ExecuteBatch provides a mock function with given fields: ctx, batch, updateMerkleTree, dbTx +func (_m *StateMock) ExecuteBatch(ctx context.Context, batch state.Batch, updateMerkleTree bool, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { + ret := _m.Called(ctx, batch, updateMerkleTree, dbTx) + + var r0 *pb.ProcessBatchResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, state.Batch, bool, pgx.Tx) (*pb.ProcessBatchResponse, error)); ok { + return rf(ctx, batch, updateMerkleTree, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, state.Batch, bool, pgx.Tx) *pb.ProcessBatchResponse); ok { + r0 = rf(ctx, batch, updateMerkleTree, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pb.ProcessBatchResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, state.Batch, bool, pgx.Tx) error); ok { + r1 = rf(ctx, batch, updateMerkleTree, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FlushMerkleTree provides a mock function with given fields: ctx +func (_m *StateMock) FlushMerkleTree(ctx context.Context) error { + ret := _m.Called(ctx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetBalanceByStateRoot provides a mock function with given fields: ctx, address, root +func (_m *StateMock) GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + ret := _m.Called(ctx, address, root) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) (*big.Int, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) *big.Int); ok { + r0 = rf(ctx, address, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetForcedBatch provides a mock function with given fields: ctx, forcedBatchNumber, dbTx +func (_m *StateMock) GetForcedBatch(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (*state.ForcedBatch, error) { + ret := _m.Called(ctx, forcedBatchNumber, dbTx) + + var r0 *state.ForcedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.ForcedBatch, error)); ok { + return rf(ctx, forcedBatchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.ForcedBatch); ok { + r0 = rf(ctx, forcedBatchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.ForcedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, forcedBatchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetForcedBatchesSince provides a mock function with given fields: ctx, forcedBatchNumber, maxBlockNumber, dbTx +func (_m *StateMock) GetForcedBatchesSince(ctx context.Context, forcedBatchNumber uint64, maxBlockNumber uint64, dbTx pgx.Tx) ([]*state.ForcedBatch, error) { + ret := _m.Called(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + + var r0 []*state.ForcedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) ([]*state.ForcedBatch, error)); ok { + return rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) []*state.ForcedBatch); ok { + r0 = rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*state.ForcedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, forcedBatchNumber, maxBlockNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBatch provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBatchNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastBlock provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Block, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Block, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Block); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastClosedBatch provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastClosedBatch(ctx context.Context, dbTx pgx.Tx) (*state.Batch, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Batch); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastL2Block provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *types.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*types.Block, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *types.Block); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Block) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastL2BlockHeader provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*types.Header, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *types.Header); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Header) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastNBatches provides a mock function with given fields: ctx, numBatches, dbTx +func (_m *StateMock) GetLastNBatches(ctx context.Context, numBatches uint, dbTx pgx.Tx) ([]*state.Batch, error) { + ret := _m.Called(ctx, numBatches, dbTx) + + var r0 []*state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint, pgx.Tx) ([]*state.Batch, error)); ok { + return rf(ctx, numBatches, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint, pgx.Tx) []*state.Batch); ok { + r0 = rf(ctx, numBatches, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*state.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint, pgx.Tx) error); ok { + r1 = rf(ctx, numBatches, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastStateRoot provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastStateRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) { + ret := _m.Called(ctx, dbTx) + + var r0 common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (common.Hash, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) common.Hash); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastTrustedForcedBatchNumber provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVirtualBatchNum provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLatestGer provides a mock function with given fields: ctx, maxBlockNumber +func (_m *StateMock) GetLatestGer(ctx context.Context, maxBlockNumber uint64) (state.GlobalExitRoot, time.Time, error) { + ret := _m.Called(ctx, maxBlockNumber) + + var r0 state.GlobalExitRoot + var r1 time.Time + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (state.GlobalExitRoot, time.Time, error)); ok { + return rf(ctx, maxBlockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) state.GlobalExitRoot); ok { + r0 = rf(ctx, maxBlockNumber) + } else { + r0 = ret.Get(0).(state.GlobalExitRoot) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) time.Time); ok { + r1 = rf(ctx, maxBlockNumber) + } else { + r1 = ret.Get(1).(time.Time) + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64) error); ok { + r2 = rf(ctx, maxBlockNumber) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetLatestGlobalExitRoot provides a mock function with given fields: ctx, maxBlockNumber, dbTx +func (_m *StateMock) GetLatestGlobalExitRoot(ctx context.Context, maxBlockNumber uint64, dbTx pgx.Tx) (state.GlobalExitRoot, time.Time, error) { + ret := _m.Called(ctx, maxBlockNumber, dbTx) + + var r0 state.GlobalExitRoot + var r1 time.Time + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (state.GlobalExitRoot, time.Time, error)); ok { + return rf(ctx, maxBlockNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) state.GlobalExitRoot); ok { + r0 = rf(ctx, maxBlockNumber, dbTx) + } else { + r0 = ret.Get(0).(state.GlobalExitRoot) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) time.Time); ok { + r1 = rf(ctx, maxBlockNumber, dbTx) + } else { + r1 = ret.Get(1).(time.Time) + } + + if rf, ok := ret.Get(2).(func(context.Context, uint64, pgx.Tx) error); ok { + r2 = rf(ctx, maxBlockNumber, dbTx) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetLatestVirtualBatchTimestamp provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { + ret := _m.Called(ctx, dbTx) + + var r0 time.Time + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (time.Time, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) time.Time); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(time.Time) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetNonceByStateRoot provides a mock function with given fields: ctx, address, root +func (_m *StateMock) GetNonceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + ret := _m.Called(ctx, address, root) + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) (*big.Int, error)); ok { + return rf(ctx, address, root) + } + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Hash) *big.Int); ok { + r0 = rf(ctx, address, root) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, common.Address, common.Hash) error); ok { + r1 = rf(ctx, address, root) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTimeForLatestBatchVirtualization provides a mock function with given fields: ctx, dbTx +func (_m *StateMock) GetTimeForLatestBatchVirtualization(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { + ret := _m.Called(ctx, dbTx) + + var r0 time.Time + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (time.Time, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) time.Time); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(time.Time) + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTransactionsByBatchNumber provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *StateMock) GetTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]types.Transaction, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 []types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) ([]types.Transaction, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) []types.Transaction); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetTxsOlderThanNL1Blocks provides a mock function with given fields: ctx, nL1Blocks, dbTx +func (_m *StateMock) GetTxsOlderThanNL1Blocks(ctx context.Context, nL1Blocks uint64, dbTx pgx.Tx) ([]common.Hash, error) { + ret := _m.Called(ctx, nL1Blocks, dbTx) + + var r0 []common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) ([]common.Hash, error)); ok { + return rf(ctx, nL1Blocks, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) []common.Hash); ok { + r0 = rf(ctx, nL1Blocks, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Hash) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, nL1Blocks, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// IsBatchClosed provides a mock function with given fields: ctx, batchNum, dbTx +func (_m *StateMock) IsBatchClosed(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (bool, error) { + ret := _m.Called(ctx, batchNum, dbTx) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (bool, error)); ok { + return rf(ctx, batchNum, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) bool); ok { + r0 = rf(ctx, batchNum, dbTx) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNum, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// OpenBatch provides a mock function with given fields: ctx, processingContext, dbTx +func (_m *StateMock) OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error { + ret := _m.Called(ctx, processingContext, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingContext, pgx.Tx) error); ok { + r0 = rf(ctx, processingContext, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ProcessBatch provides a mock function with given fields: ctx, request, updateMerkleTree +func (_m *StateMock) ProcessBatch(ctx context.Context, request state.ProcessRequest, updateMerkleTree bool) (*state.ProcessBatchResponse, error) { + ret := _m.Called(ctx, request, updateMerkleTree) + + var r0 *state.ProcessBatchResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessRequest, bool) (*state.ProcessBatchResponse, error)); ok { + return rf(ctx, request, updateMerkleTree) + } + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessRequest, bool) *state.ProcessBatchResponse); ok { + r0 = rf(ctx, request, updateMerkleTree) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.ProcessBatchResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, state.ProcessRequest, bool) error); ok { + r1 = rf(ctx, request, updateMerkleTree) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ProcessSequencerBatch provides a mock function with given fields: ctx, batchNumber, batchL2Data, caller, dbTx +func (_m *StateMock) ProcessSequencerBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) { + ret := _m.Called(ctx, batchNumber, batchL2Data, caller, dbTx) + + var r0 *state.ProcessBatchResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) (*state.ProcessBatchResponse, error)); ok { + return rf(ctx, batchNumber, batchL2Data, caller, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) *state.ProcessBatchResponse); ok { + r0 = rf(ctx, batchNumber, batchL2Data, caller, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.ProcessBatchResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, batchL2Data, caller, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StoreTransaction provides a mock function with given fields: ctx, batchNumber, processedTx, coinbase, timestamp, dbTx +func (_m *StateMock) StoreTransaction(ctx context.Context, batchNumber uint64, processedTx *state.ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, processedTx, coinbase, timestamp, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *state.ProcessTransactionResponse, common.Address, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, processedTx, coinbase, timestamp, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateBatchL2Data provides a mock function with given fields: ctx, batchNumber, batchL2Data, dbTx +func (_m *StateMock) UpdateBatchL2Data(ctx context.Context, batchNumber uint64, batchL2Data []byte, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, batchL2Data, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []byte, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, batchL2Data, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTNewStateMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewStateMock creates a new instance of StateMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewStateMock(t mockConstructorTestingTNewStateMock) *StateMock { + mock := &StateMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencer/mock_worker.go b/sequencer/mock_worker.go new file mode 100644 index 0000000000..61fcfd0ad7 --- /dev/null +++ b/sequencer/mock_worker.go @@ -0,0 +1,149 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package sequencer + +import ( + context "context" + big "math/big" + + common "github.com/ethereum/go-ethereum/common" + + mock "github.com/stretchr/testify/mock" + + state "github.com/0xPolygonHermez/zkevm-node/state" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// WorkerMock is an autogenerated mock type for the workerInterface type +type WorkerMock struct { + mock.Mock +} + +// AddTxTracker provides a mock function with given fields: ctx, txTracker +func (_m *WorkerMock) AddTxTracker(ctx context.Context, txTracker *TxTracker) (error, bool) { + ret := _m.Called(ctx, txTracker) + + var r0 error + var r1 bool + if rf, ok := ret.Get(0).(func(context.Context, *TxTracker) (error, bool)); ok { + return rf(ctx, txTracker) + } + if rf, ok := ret.Get(0).(func(context.Context, *TxTracker) error); ok { + r0 = rf(ctx, txTracker) + } else { + r0 = ret.Error(0) + } + + if rf, ok := ret.Get(1).(func(context.Context, *TxTracker) bool); ok { + r1 = rf(ctx, txTracker) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// DeleteTx provides a mock function with given fields: txHash, from +func (_m *WorkerMock) DeleteTx(txHash common.Hash, from common.Address) { + _m.Called(txHash, from) +} + +// GetBestFittingTx provides a mock function with given fields: resources +func (_m *WorkerMock) GetBestFittingTx(resources state.BatchResources) *TxTracker { + ret := _m.Called(resources) + + var r0 *TxTracker + if rf, ok := ret.Get(0).(func(state.BatchResources) *TxTracker); ok { + r0 = rf(resources) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*TxTracker) + } + } + + return r0 +} + +// HandleL2Reorg provides a mock function with given fields: txHashes +func (_m *WorkerMock) HandleL2Reorg(txHashes []common.Hash) { + _m.Called(txHashes) +} + +// MoveTxToNotReady provides a mock function with given fields: txHash, from, actualNonce, actualBalance +func (_m *WorkerMock) MoveTxToNotReady(txHash common.Hash, from common.Address, actualNonce *uint64, actualBalance *big.Int) []*TxTracker { + ret := _m.Called(txHash, from, actualNonce, actualBalance) + + var r0 []*TxTracker + if rf, ok := ret.Get(0).(func(common.Hash, common.Address, *uint64, *big.Int) []*TxTracker); ok { + r0 = rf(txHash, from, actualNonce, actualBalance) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*TxTracker) + } + } + + return r0 +} + +// NewTxTracker provides a mock function with given fields: tx, counters, ip +func (_m *WorkerMock) NewTxTracker(tx types.Transaction, counters state.ZKCounters, ip string) (*TxTracker, error) { + ret := _m.Called(tx, counters, ip) + + var r0 *TxTracker + var r1 error + if rf, ok := ret.Get(0).(func(types.Transaction, state.ZKCounters, string) (*TxTracker, error)); ok { + return rf(tx, counters, ip) + } + if rf, ok := ret.Get(0).(func(types.Transaction, state.ZKCounters, string) *TxTracker); ok { + r0 = rf(tx, counters, ip) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*TxTracker) + } + } + + if rf, ok := ret.Get(1).(func(types.Transaction, state.ZKCounters, string) error); ok { + r1 = rf(tx, counters, ip) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateAfterSingleSuccessfulTxExecution provides a mock function with given fields: from, touchedAddresses +func (_m *WorkerMock) UpdateAfterSingleSuccessfulTxExecution(from common.Address, touchedAddresses map[common.Address]*state.InfoReadWrite) []*TxTracker { + ret := _m.Called(from, touchedAddresses) + + var r0 []*TxTracker + if rf, ok := ret.Get(0).(func(common.Address, map[common.Address]*state.InfoReadWrite) []*TxTracker); ok { + r0 = rf(from, touchedAddresses) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*TxTracker) + } + } + + return r0 +} + +// UpdateTx provides a mock function with given fields: txHash, from, ZKCounters +func (_m *WorkerMock) UpdateTx(txHash common.Hash, from common.Address, ZKCounters state.ZKCounters) { + _m.Called(txHash, from, ZKCounters) +} + +type mockConstructorTestingTNewWorkerMock interface { + mock.TestingT + Cleanup(func()) +} + +// NewWorkerMock creates a new instance of WorkerMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewWorkerMock(t mockConstructorTestingTNewWorkerMock) *WorkerMock { + mock := &WorkerMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/sequencer/mocks/mock_txmanager.go b/sequencer/mocks/mock_txmanager.go deleted file mode 100644 index 3befc52ed5..0000000000 --- a/sequencer/mocks/mock_txmanager.go +++ /dev/null @@ -1,34 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package mocks - -import ( - mock "github.com/stretchr/testify/mock" - - types "github.com/0xPolygonHermez/zkevm-node/etherman/types" -) - -// TxmanagerMock is an autogenerated mock type for the txManager type -type TxmanagerMock struct { - mock.Mock -} - -// SequenceBatches provides a mock function with given fields: sequences -func (_m *TxmanagerMock) SequenceBatches(sequences []types.Sequence) { - _m.Called(sequences) -} - -type mockConstructorTestingTNewTxmanagerMock interface { - mock.TestingT - Cleanup(func()) -} - -// NewTxmanagerMock creates a new instance of TxmanagerMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewTxmanagerMock(t mockConstructorTestingTNewTxmanagerMock) *TxmanagerMock { - mock := &TxmanagerMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sequencer/pendingtxsqueue.go b/sequencer/pendingtxsqueue.go deleted file mode 100644 index 9df3a3a5ff..0000000000 --- a/sequencer/pendingtxsqueue.go +++ /dev/null @@ -1,208 +0,0 @@ -package sequencer - -import ( - "context" - "sync" - "time" - - "github.com/0xPolygonHermez/zkevm-node/config/types" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/ethereum/go-ethereum/common" -) - -const amountOfPendingTxsRequested = 1000 - -// PendingTxsQueueConfig config for pending tx queue data structure -type PendingTxsQueueConfig struct { - TxPendingInQueueCheckingFrequency types.Duration `mapstructure:"TxPendingInQueueCheckingFrequency"` - GetPendingTxsFrequency types.Duration `mapstructure:"GetPendingTxsFrequency"` -} - -// PendingTxsQueue keeps pending tx queue and gives tx with the highest gas price by request -type PendingTxsQueue struct { - cfg PendingTxsQueueConfig - - poppedTxsHashesChan chan common.Hash - poppedTxsHashesMap map[string]bool - poppedTxsHashesMutex sync.RWMutex - - pendingTxs []pool.Transaction - pendingTxsMutex sync.RWMutex - pendingTxsMap map[string]bool - - txPool txPool -} - -// NewPendingTxsQueue inits new pending tx queue -func NewPendingTxsQueue(cfg PendingTxsQueueConfig, pool txPool) *PendingTxsQueue { - poppedTxsChan := make(chan common.Hash, amountOfPendingTxsRequested) - poppedTxsHashesMap := make(map[string]bool) - pendingTxMap := make(map[string]bool) - return &PendingTxsQueue{ - cfg: cfg, - txPool: pool, - pendingTxsMap: pendingTxMap, - poppedTxsHashesChan: poppedTxsChan, - poppedTxsHashesMap: poppedTxsHashesMap, - } -} - -// PopPendingTx pops top pending tx from the queue -func (q *PendingTxsQueue) PopPendingTx() *pool.Transaction { - var tx *pool.Transaction - - q.pendingTxsMutex.Lock() - if len(q.pendingTxs) > 1 { - tx, q.pendingTxs = &q.pendingTxs[0], q.pendingTxs[1:] - } else if len(q.pendingTxs) == 1 { - tx = &q.pendingTxs[0] - q.pendingTxs = []pool.Transaction{} - } else { - q.pendingTxsMutex.Unlock() - return nil - } - txHash := tx.Hash().Hex() - delete(q.pendingTxsMap, txHash) - q.pendingTxsMutex.Unlock() - - q.poppedTxsHashesMutex.Lock() - q.poppedTxsHashesMap[txHash] = true - q.poppedTxsHashesMutex.Unlock() - - q.poppedTxsHashesChan <- tx.Hash() - - return tx -} - -// findPlaceInSlice finds place where to insert tx to the queue according to gas amount -func (q *PendingTxsQueue) findPlaceInSlice(pendingTx pool.Transaction) int { - q.pendingTxsMutex.RLock() - defer q.pendingTxsMutex.RUnlock() - low := 0 - high := len(q.pendingTxs) - 1 - for low <= high { - median := low + (high-low)/2 // nolint:gomnd - if q.pendingTxs[median].Gas() == pendingTx.Gas() { - return median - } else if q.pendingTxs[median].Gas() < pendingTx.Gas() { - low = median + 1 - } else { - high = median - 1 - } - } - return high + 1 -} - -// InsertPendingTx insert pending tx from the pool to the queue -func (q *PendingTxsQueue) InsertPendingTx(tx pool.Transaction) { - index := q.findPlaceInSlice(tx) - q.pendingTxsMutex.Lock() - defer q.pendingTxsMutex.Unlock() - q.pendingTxsMap[tx.Hash().Hex()] = true - if index <= 1 { - q.pendingTxs = append(q.pendingTxs, tx) - } else { - q.pendingTxs = append(q.pendingTxs[:index+1], q.pendingTxs[index:]...) - q.pendingTxs[index] = tx - } -} - -// CleanPendTxsChan cleans pending tx that is already popped from the queue and selected/rejected -func (q *PendingTxsQueue) CleanPendTxsChan(ctx context.Context) { - for { - select { - case hash := <-q.poppedTxsHashesChan: - q.waitForTxToBeProcessed(ctx, hash) - case <-ctx.Done(): - return - } - } -} - -// waitForTxToBeProcessed for the tx to change it's status from pending to invalid or selected -func (q *PendingTxsQueue) waitForTxToBeProcessed(ctx context.Context, hash common.Hash) { - var err error - tickerIsTxPending := time.NewTicker(q.cfg.TxPendingInQueueCheckingFrequency.Duration) - isPending := true - for isPending { - isPending, err = q.txPool.IsTxPending(ctx, hash) - if err != nil { - log.Warnf("failed to check if tx is still pending, txHash: %s, err: %v", hash.Hex(), err) - } - - if !isPending { - q.poppedTxsHashesMutex.Lock() - delete(q.poppedTxsHashesMap, hash.Hex()) - q.poppedTxsHashesMutex.Unlock() - return - } - select { - case <-tickerIsTxPending.C: - // nothing - case <-ctx.Done(): - return - } - } -} - -// KeepPendingTxsQueue keeps pending txs queue full -func (q *PendingTxsQueue) KeepPendingTxsQueue(ctx context.Context) { - var err error - q.pendingTxsMutex.Lock() - for len(q.pendingTxs) == 0 { - q.pendingTxs, err = q.txPool.GetPendingTxs(ctx, false, amountOfPendingTxsRequested) - if err != nil { - log.Errorf("failed to get pending txs, err: %v", err) - } - if len(q.pendingTxs) == 0 { - time.Sleep(q.cfg.GetPendingTxsFrequency.Duration) - } - } - - for _, tx := range q.pendingTxs { - q.pendingTxsMap[tx.Hash().Hex()] = true - } - - q.pendingTxsMutex.Unlock() - - for { - time.Sleep(q.cfg.GetPendingTxsFrequency.Duration) - lenPendingTxs := q.GetPendingTxsQueueLength() - if lenPendingTxs >= amountOfPendingTxsRequested { - continue - } - pendTx, err := q.txPool.GetPendingTxs(ctx, false, 1) - if err != nil { - log.Errorf("failed to get pending tx, err: %v", err) - continue - } - if len(pendTx) == 0 { - continue - } - pendTxHash := pendTx[0].Hash().Hex() - if lenPendingTxs == 0 || - !(q.isTxPopped(pendTxHash) || q.isTxInPendingQueue(pendTxHash)) { - q.InsertPendingTx(pendTx[0]) - } - } -} - -// GetPendingTxsQueueLength get length -func (q *PendingTxsQueue) GetPendingTxsQueueLength() int { - q.pendingTxsMutex.RLock() - defer q.pendingTxsMutex.RUnlock() - return len(q.pendingTxs) -} - -func (q *PendingTxsQueue) isTxInPendingQueue(txHash string) bool { - q.pendingTxsMutex.RLock() - defer q.pendingTxsMutex.RUnlock() - return q.pendingTxsMap[txHash] -} - -func (q *PendingTxsQueue) isTxPopped(txHash string) bool { - q.poppedTxsHashesMutex.RLock() - defer q.poppedTxsHashesMutex.RUnlock() - return q.poppedTxsHashesMap[txHash] -} diff --git a/sequencer/pendingtxsqueue_test.go b/sequencer/pendingtxsqueue_test.go deleted file mode 100644 index 2a4818ba12..0000000000 --- a/sequencer/pendingtxsqueue_test.go +++ /dev/null @@ -1,227 +0,0 @@ -package sequencer_test - -import ( - "context" - "fmt" - "math/big" - "strings" - "testing" - "time" - - cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" - "github.com/0xPolygonHermez/zkevm-node/db" - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/sequencer" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" - "github.com/0xPolygonHermez/zkevm-node/test/dbutils" - "github.com/0xPolygonHermez/zkevm-node/test/testutils" - "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/jackc/pgx/v4/pgxpool" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var ( - senderPrivateKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" - - stateDBCfg = dbutils.NewStateConfigFromEnv() - poolDBCfg = dbutils.NewPoolConfigFromEnv() - - queueCfg = sequencer.PendingTxsQueueConfig{ - TxPendingInQueueCheckingFrequency: cfgTypes.NewDuration(1 * time.Second), - GetPendingTxsFrequency: cfgTypes.NewDuration(1 * time.Second), - } - - genesis = state.Genesis{ - Actions: []*state.GenesisAction{ - { - Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - Type: int(merkletree.LeafTypeBalance), - Value: "1000000000000000000000", - }, - }, - } - - chainID = big.NewInt(1337) -) - -func TestQueue_AddAndPopTx(t *testing.T) { - initOrResetDB() - - sqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - panic(err) - } - defer sqlDB.Close() //nolint:gosec,errcheck - - st := newState(sqlDB) - - genesisBlock := state.Block{ - BlockNumber: 0, - BlockHash: state.ZeroHash, - ParentHash: state.ZeroHash, - ReceivedAt: time.Now(), - } - ctx := context.Background() - dbTx, err := st.BeginStateTransaction(ctx) - require.NoError(t, err) - _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) - require.NoError(t, err) - require.NoError(t, dbTx.Commit(ctx)) - - s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - panic(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) - - const txsCount = 10 - - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) - if err != nil { - panic(err) - } - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) - if err != nil { - panic(err) - } - - pendQueue := sequencer.NewPendingTxsQueue(queueCfg, p) - go pendQueue.KeepPendingTxsQueue(ctx) - go pendQueue.CleanPendTxsChan(ctx) - // insert pending transactions - for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(i)), []byte{}) - signedTx, err := auth.Signer(auth.From, tx) - if err != nil { - panic(err) - } - if err := p.AddTx(ctx, *signedTx); err != nil { - panic(err) - } - } - tx := pendQueue.PopPendingTx() - assert.Equal(t, uint64(19), tx.GasPrice().Uint64()) - assert.Equal(t, 9, pendQueue.GetPendingTxsQueueLength()) - tx = pendQueue.PopPendingTx() - assert.Equal(t, uint64(18), tx.GasPrice().Uint64()) - assert.Equal(t, 8, pendQueue.GetPendingTxsQueueLength()) - - newTx := types.NewTransaction(uint64(txsCount), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(txsCount)), []byte{}) - signedTx, err := auth.Signer(auth.From, newTx) - if err != nil { - panic(err) - } - if err := p.AddTx(ctx, *signedTx); err != nil { - panic(err) - } - - time.Sleep(queueCfg.TxPendingInQueueCheckingFrequency.Duration * 2) - assert.Equal(t, 9, pendQueue.GetPendingTxsQueueLength()) -} - -func TestQueue_AddOneTx(t *testing.T) { - initOrResetDB() - - sqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - panic(err) - } - defer sqlDB.Close() //nolint:gosec,errcheck - - st := newState(sqlDB) - - genesisBlock := state.Block{ - BlockNumber: 0, - BlockHash: state.ZeroHash, - ParentHash: state.ZeroHash, - ReceivedAt: time.Now(), - } - ctx := context.Background() - dbTx, err := st.BeginStateTransaction(ctx) - require.NoError(t, err) - _, err = st.SetGenesis(ctx, genesisBlock, genesis, dbTx) - require.NoError(t, err) - require.NoError(t, dbTx.Commit(ctx)) - - s, err := pgpoolstorage.NewPostgresPoolStorage(poolDBCfg) - if err != nil { - panic(err) - } - - p := pool.NewPool(s, st, common.Address{}, chainID.Uint64()) - - const txsCount = 1 - - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) - if err != nil { - panic(err) - } - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) - if err != nil { - panic(err) - } - - pendQueue := sequencer.NewPendingTxsQueue(queueCfg, p) - go pendQueue.KeepPendingTxsQueue(ctx) - go pendQueue.CleanPendTxsChan(ctx) - // insert pending transactions - for i := 0; i < txsCount; i++ { - tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(i)), []byte{}) - signedTx, err := auth.Signer(auth.From, tx) - if err != nil { - panic(err) - } - if err := p.AddTx(ctx, *signedTx); err != nil { - panic(err) - } - } - tx := pendQueue.PopPendingTx() - assert.Equal(t, uint64(10), tx.GasPrice().Uint64()) - assert.Equal(t, 0, pendQueue.GetPendingTxsQueueLength()) - tx = pendQueue.PopPendingTx() - assert.Nil(t, tx) - - newTx := types.NewTransaction(uint64(txsCount), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10+int64(txsCount)), []byte{}) - signedTx, err := auth.Signer(auth.From, newTx) - if err != nil { - panic(err) - } - if err := p.AddTx(ctx, *signedTx); err != nil { - panic(err) - } - time.Sleep(queueCfg.TxPendingInQueueCheckingFrequency.Duration * 2) - assert.Equal(t, 1, pendQueue.GetPendingTxsQueueLength()) -} - -func newState(sqlDB *pgxpool.Pool) *state.State { - ctx := context.Background() - stateDb := state.NewPostgresStorage(sqlDB) - zkProverURI := testutils.GetEnv("ZKPROVER_URI", "localhost") - - executorServerConfig := executor.Config{URI: fmt.Sprintf("%s:50071", zkProverURI)} - mtDBServerConfig := merkletree.Config{URI: fmt.Sprintf("%s:50061", zkProverURI)} - executorClient, _, _ := executor.NewExecutorClient(ctx, executorServerConfig) - stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, mtDBServerConfig) - stateTree := merkletree.NewStateTree(stateDBClient) - st := state.NewState(state.Config{MaxCumulativeGasUsed: 800000}, stateDb, executorClient, stateTree) - return st -} - -func initOrResetDB() { - if err := dbutils.InitOrResetState(stateDBCfg); err != nil { - panic(err) - } - if err := dbutils.InitOrResetPool(poolDBCfg); err != nil { - panic(err) - } -} diff --git a/sequencer/profitabilitychecker/config.go b/sequencer/profitabilitychecker/config.go deleted file mode 100644 index 24c8d1dec5..0000000000 --- a/sequencer/profitabilitychecker/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package profitabilitychecker - -// Config for profitability checker -type Config struct { - // SendBatchesEvenWhenNotProfitable if true -> send unprofitable batch - SendBatchesEvenWhenNotProfitable bool `mapstructure:"SendBatchesEvenWhenNotProfitable"` -} diff --git a/sequencer/profitabilitychecker/interfaces.go b/sequencer/profitabilitychecker/interfaces.go deleted file mode 100644 index cc62ee61b9..0000000000 --- a/sequencer/profitabilitychecker/interfaces.go +++ /dev/null @@ -1,19 +0,0 @@ -package profitabilitychecker - -import ( - "context" - "math/big" -) - -// Consumer interfaces required by the package. - -// etherman contains the methods required to interact with ethereum. -type etherman interface { - GetSendSequenceFee() (*big.Int, error) -} - -// priceGetter is for getting eth/matic price, used for the base tx profitability checker -type priceGetter interface { - Start(ctx context.Context) - GetEthToMaticPrice(ctx context.Context) (*big.Float, error) -} diff --git a/sequencer/profitabilitychecker/mocks/mock_etherman.go b/sequencer/profitabilitychecker/mocks/mock_etherman.go deleted file mode 100644 index 8bfcd1eb4a..0000000000 --- a/sequencer/profitabilitychecker/mocks/mock_etherman.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package mocks - -import ( - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// EthermanMock is an autogenerated mock type for the etherman type -type EthermanMock struct { - mock.Mock -} - -// GetSendSequenceFee provides a mock function with given fields: -func (_m *EthermanMock) GetSendSequenceFee() (*big.Int, error) { - ret := _m.Called() - - var r0 *big.Int - if rf, ok := ret.Get(0).(func() *big.Int); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewEthermanMock interface { - mock.TestingT - Cleanup(func()) -} - -// NewEthermanMock creates a new instance of EthermanMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewEthermanMock(t mockConstructorTestingTNewEthermanMock) *EthermanMock { - mock := &EthermanMock{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/sequencer/profitabilitychecker/profitabilitychecker.go b/sequencer/profitabilitychecker/profitabilitychecker.go deleted file mode 100644 index 97f094fb1a..0000000000 --- a/sequencer/profitabilitychecker/profitabilitychecker.go +++ /dev/null @@ -1,87 +0,0 @@ -package profitabilitychecker - -import ( - "context" - "math/big" - - "github.com/0xPolygonHermez/zkevm-node/etherman/types" - "github.com/0xPolygonHermez/zkevm-node/pricegetter" -) - -// Checker checks profitability to send sequences -type Checker struct { - Config Config - EthMan etherman - PriceGetter pricegetter.Client -} - -// New creates new profitability checker -func New( - cfg Config, - etherMan etherman, - priceGetter priceGetter) *Checker { - return &Checker{ - Config: cfg, - EthMan: etherMan, - PriceGetter: priceGetter, - } -} - -// IsSequenceProfitable check if sequence is profitable by comparing L1 tx gas cost and collateral with fee rewards -func (c *Checker) IsSequenceProfitable(ctx context.Context, sequence types.Sequence) (bool, error) { - if c.Config.SendBatchesEvenWhenNotProfitable { - return true, nil - } - // fee - it's collateral for batch, get from SC in matic - fee, err := c.EthMan.GetSendSequenceFee() - if err != nil { - return false, err - } - - // this reward is in ethereum wei - reward := big.NewInt(0) - for _, tx := range sequence.Txs { - reward.Add(reward, new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))) - } - - // get price of matic (1 eth = x matic) - price, err := c.PriceGetter.GetEthToMaticPrice(ctx) - if err != nil { - return false, err - } - - // convert reward in eth to reward in matic - priceInt := new(big.Int) - price.Int(priceInt) - reward.Mul(reward, priceInt) - - if reward.Cmp(fee) < 0 { - return false, nil - } - - return true, nil -} - -// IsSendSequencesProfitable checks profitability to send sequences to the ethereum -func (c *Checker) IsSendSequencesProfitable(estimatedGas *big.Int, sequences []types.Sequence) bool { - if len(sequences) == 0 { - return false - } - if c.Config.SendBatchesEvenWhenNotProfitable { - return true - } - - gasCostSequences := big.NewInt(0) - for _, seq := range sequences { - for _, tx := range seq.Txs { - gasCostSequences.Add(gasCostSequences, new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))) - if gasCostSequences.Cmp(estimatedGas) > 0 { - return true - } - } - } - - // TODO: consider MATIC fee - - return false -} diff --git a/sequencer/profitabilitychecker/profitabilitychecker_test.go b/sequencer/profitabilitychecker/profitabilitychecker_test.go deleted file mode 100644 index 47932b5f2d..0000000000 --- a/sequencer/profitabilitychecker/profitabilitychecker_test.go +++ /dev/null @@ -1,115 +0,0 @@ -package profitabilitychecker_test - -import ( - "context" - "math/big" - "testing" - - ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" - "github.com/0xPolygonHermez/zkevm-node/pricegetter" - "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker" - "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker/mocks" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" -) - -func Test_IsSequenceProfitable(t *testing.T) { - ethman := new(mocks.EthermanMock) - ethman.On("GetSendSequenceFee").Return(big.NewInt(0), nil) - - pg, err := pricegetter.NewClient(pricegetter.Config{ - Type: "default", - DefaultPrice: pricegetter.TokenPrice{Float: big.NewFloat(2000)}, - }) - require.NoError(t, err) - - pc := profitabilitychecker.New(profitabilitychecker.Config{SendBatchesEvenWhenNotProfitable: false}, ethman, pg) - - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx3 := types.NewTransaction(uint64(2), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - - sequence := ethmanTypes.Sequence{ - Txs: []types.Transaction{*tx1, *tx2, *tx3}, - } - ctx := context.Background() - isProfitable, err := pc.IsSequenceProfitable(ctx, sequence) - require.NoError(t, err) - require.True(t, isProfitable) -} - -func Test_IsSequenceProfitableFalse(t *testing.T) { - ethman := new(mocks.EthermanMock) - ethman.On("GetSendSequenceFee").Return(big.NewInt(10000000), nil) - - pg, err := pricegetter.NewClient(pricegetter.Config{ - Type: "default", - DefaultPrice: pricegetter.TokenPrice{Float: big.NewFloat(2000)}, - }) - require.NoError(t, err) - - pc := profitabilitychecker.New(profitabilitychecker.Config{SendBatchesEvenWhenNotProfitable: false}, ethman, pg) - - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx3 := types.NewTransaction(uint64(2), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - - sequence := ethmanTypes.Sequence{ - Txs: []types.Transaction{*tx1, *tx2, *tx3}, - } - ctx := context.Background() - isProfitable, err := pc.IsSequenceProfitable(ctx, sequence) - require.NoError(t, err) - require.False(t, isProfitable) -} - -func Test_IsSendSequencesProfitable(t *testing.T) { - ethman := new(mocks.EthermanMock) - - pg, err := pricegetter.NewClient(pricegetter.Config{ - Type: "default", - DefaultPrice: pricegetter.TokenPrice{Float: big.NewFloat(2000)}, - }) - require.NoError(t, err) - - pc := profitabilitychecker.New(profitabilitychecker.Config{SendBatchesEvenWhenNotProfitable: false}, ethman, pg) - - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(1000), []byte{}) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(1000), []byte{}) - tx3 := types.NewTransaction(uint64(2), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(1000), []byte{}) - - sequence := ethmanTypes.Sequence{ - Txs: []types.Transaction{*tx1, *tx2, *tx3}, - } - - estGas := big.NewInt(100) - isProfitable := pc.IsSendSequencesProfitable(estGas, []ethmanTypes.Sequence{sequence}) - - require.True(t, isProfitable) -} - -func Test_IsSendSequencesFalse(t *testing.T) { - ethman := new(mocks.EthermanMock) - - pg, err := pricegetter.NewClient(pricegetter.Config{ - Type: "default", - DefaultPrice: pricegetter.TokenPrice{Float: big.NewFloat(2000)}, - }) - require.NoError(t, err) - - pc := profitabilitychecker.New(profitabilitychecker.Config{SendBatchesEvenWhenNotProfitable: false}, ethman, pg) - - tx1 := types.NewTransaction(uint64(0), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx2 := types.NewTransaction(uint64(1), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - tx3 := types.NewTransaction(uint64(2), common.Address{}, big.NewInt(10), uint64(1), big.NewInt(10), []byte{}) - - sequence := ethmanTypes.Sequence{ - Txs: []types.Transaction{*tx1, *tx2, *tx3}, - } - - estGas := big.NewInt(100) - isProfitable := pc.IsSendSequencesProfitable(estGas, []ethmanTypes.Sequence{sequence}) - - require.False(t, isProfitable) -} diff --git a/sequencer/sequencer.go b/sequencer/sequencer.go index 8622ed02d7..038f2e3974 100644 --- a/sequencer/sequencer.go +++ b/sequencer/sequencer.go @@ -4,66 +4,101 @@ import ( "context" "errors" "fmt" + "sync" "time" - "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/event" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics" "github.com/0xPolygonHermez/zkevm-node/state" + stateMetrics "github.com/0xPolygonHermez/zkevm-node/state/metrics" "github.com/ethereum/go-ethereum/common" - ethTypes "github.com/ethereum/go-ethereum/core/types" -) - -const ( - errGasRequiredExceedsAllowance = "gas required exceeds allowance" - errContentLengthTooLarge = "content length too large" - errTimestampMustBeInsideRange = "Timestamp must be inside range" - errInsufficientAllowance = "insufficient allowance" ) // Sequencer represents a sequencer type Sequencer struct { cfg Config - pool txPool - state stateInterface - txManager txManager - etherman etherman - checker *profitabilitychecker.Checker - gpe gasPriceEstimator + pool txPool + state stateInterface + eventLog *event.EventLog + ethTxManager ethTxManager + etherman etherman - address common.Address - isSequenceTooBig bool + address common.Address +} - sequenceInProgress types.Sequence +// batchConstraints represents the constraints for a batch +type batchConstraints struct { + MaxTxsPerBatch uint64 + MaxBatchBytesSize uint64 + MaxCumulativeGasUsed uint64 + MaxKeccakHashes uint32 + MaxPoseidonHashes uint32 + MaxPoseidonPaddings uint32 + MaxMemAligns uint32 + MaxArithmetics uint32 + MaxBinaries uint32 + MaxSteps uint32 } -// New init sequencer -func New( - cfg Config, - txPool txPool, - state stateInterface, - etherman etherman, - priceGetter priceGetter, - manager txManager, - gpe gasPriceEstimator) (*Sequencer, error) { - checker := profitabilitychecker.New(cfg.ProfitabilityChecker, etherman, priceGetter) +// TODO: Add tests to config_test.go +type batchResourceWeights struct { + WeightBatchBytesSize int + WeightCumulativeGasUsed int + WeightKeccakHashes int + WeightPoseidonHashes int + WeightPoseidonPaddings int + WeightMemAligns int + WeightArithmetics int + WeightBinaries int + WeightSteps int +} + +// L2ReorgEvent is the event that is triggered when a reorg happens in the L2 +type L2ReorgEvent struct { + TxHashes []common.Hash +} + +// ClosingSignalCh is a struct that contains all the channels that are used to receive batch closing signals +type ClosingSignalCh struct { + ForcedBatchCh chan state.ForcedBatch + GERCh chan common.Hash + L2ReorgCh chan L2ReorgEvent +} + +// TxsStore is a struct that contains the channel and the wait group for the txs to be stored in order +type TxsStore struct { + Ch chan *txToStore + Wg *sync.WaitGroup +} + +// txToStore represents a transaction to store. +type txToStore struct { + txResponse *state.ProcessTransactionResponse + batchNumber uint64 + coinbase common.Address + timestamp uint64 + previousL2BlockStateRoot common.Hash + isForcedBatch bool +} +// New init sequencer +func New(cfg Config, txPool txPool, state stateInterface, etherman etherman, manager ethTxManager, eventLog *event.EventLog) (*Sequencer, error) { addr, err := etherman.TrustedSequencer() if err != nil { return nil, fmt.Errorf("failed to get trusted sequencer address, err: %v", err) } - // TODO: check that private key used in etherman matches addr return &Sequencer{ - cfg: cfg, - pool: txPool, - state: state, - etherman: etherman, - checker: checker, - txManager: manager, - gpe: gpe, - address: addr, + cfg: cfg, + pool: txPool, + state: state, + etherman: etherman, + ethTxManager: manager, + address: addr, + eventLog: eventLog, }, nil } @@ -73,59 +108,154 @@ func (s *Sequencer) Start(ctx context.Context) { log.Infof("waiting for synchronizer to sync...") time.Sleep(s.cfg.WaitPeriodPoolIsEmpty.Duration) } - // initialize sequence - batchNum, err := s.state.GetLastBatchNumber(ctx, nil) + metrics.Register() + + closingSignalCh := ClosingSignalCh{ + ForcedBatchCh: make(chan state.ForcedBatch), + GERCh: make(chan common.Hash), + L2ReorgCh: make(chan L2ReorgEvent), + } + + txsStore := TxsStore{ + Ch: make(chan *txToStore), + Wg: new(sync.WaitGroup), + } + + batchConstraints := batchConstraints{ + MaxTxsPerBatch: s.cfg.MaxTxsPerBatch, + MaxBatchBytesSize: s.cfg.MaxBatchBytesSize, + MaxCumulativeGasUsed: s.cfg.MaxCumulativeGasUsed, + MaxKeccakHashes: s.cfg.MaxKeccakHashes, + MaxPoseidonHashes: s.cfg.MaxPoseidonHashes, + MaxPoseidonPaddings: s.cfg.MaxPoseidonPaddings, + MaxMemAligns: s.cfg.MaxMemAligns, + MaxArithmetics: s.cfg.MaxArithmetics, + MaxBinaries: s.cfg.MaxBinaries, + MaxSteps: s.cfg.MaxSteps, + } + batchResourceWeights := batchResourceWeights{ + WeightBatchBytesSize: s.cfg.WeightBatchBytesSize, + WeightCumulativeGasUsed: s.cfg.WeightCumulativeGasUsed, + WeightKeccakHashes: s.cfg.WeightKeccakHashes, + WeightPoseidonHashes: s.cfg.WeightPoseidonHashes, + WeightPoseidonPaddings: s.cfg.WeightPoseidonPaddings, + WeightMemAligns: s.cfg.WeightMemAligns, + WeightArithmetics: s.cfg.WeightArithmetics, + WeightBinaries: s.cfg.WeightBinaries, + WeightSteps: s.cfg.WeightSteps, + } + + err := s.pool.MarkWIPTxsAsPending(ctx) + if err != nil { + log.Fatalf("failed to mark WIP txs as pending, err: %v", err) + } + + worker := NewWorker(s.cfg.Worker, s.state, batchConstraints, batchResourceWeights) + dbManager := newDBManager(ctx, s.cfg.DBManager, s.pool, s.state, worker, closingSignalCh, txsStore, batchConstraints) + go dbManager.Start() + + finalizer := newFinalizer(s.cfg.Finalizer, worker, dbManager, s.state, s.address, s.isSynced, closingSignalCh, txsStore, batchConstraints, s.eventLog) + currBatch, processingReq := s.bootstrap(ctx, dbManager, finalizer) + go finalizer.Start(ctx, currBatch, processingReq) + + closingSignalsManager := newClosingSignalsManager(ctx, finalizer.dbManager, closingSignalCh, finalizer.cfg, s.etherman) + go closingSignalsManager.Start() + + go s.trackOldTxs(ctx) + tickerProcessTxs := time.NewTicker(s.cfg.WaitPeriodPoolIsEmpty.Duration) + defer tickerProcessTxs.Stop() + + // Expire too old txs in the worker + go func() { + for { + time.Sleep(s.cfg.TxLifetimeCheckTimeout.Duration) + txTrackers := worker.ExpireTransactions(s.cfg.MaxTxLifetime.Duration) + failedReason := ErrExpiredTransaction.Error() + for _, txTracker := range txTrackers { + err := s.pool.UpdateTxStatus(ctx, txTracker.Hash, pool.TxStatusFailed, false, &failedReason) + if err != nil { + log.Errorf("failed to update tx status, err: %v", err) + } + } + } + }() + + // Wait until context is done + <-ctx.Done() +} + +func (s *Sequencer) bootstrap(ctx context.Context, dbManager *dbManager, finalizer *finalizer) (*WipBatch, *state.ProcessRequest) { + var ( + currBatch *WipBatch + processRequest *state.ProcessRequest + ) + + batchNum, err := dbManager.GetLastBatchNumber(ctx) for err != nil { if errors.Is(err, state.ErrStateNotSynchronized) { log.Warnf("state is not synchronized, trying to get last batch num once again...") time.Sleep(s.cfg.WaitPeriodPoolIsEmpty.Duration) - batchNum, err = s.state.GetLastBatchNumber(ctx, nil) + batchNum, err = dbManager.GetLastBatchNumber(ctx) } else { log.Fatalf("failed to get last batch number, err: %v", err) } } - // case A: genesis if batchNum == 0 { - s.createFirstBatch(ctx) + /////////////////// + // GENESIS Batch // + /////////////////// + processingCtx := dbManager.CreateFirstBatch(ctx, s.address) + timestamp := processingCtx.Timestamp + _, oldStateRoot, err := finalizer.getLastBatchNumAndOldStateRoot(ctx) + if err != nil { + log.Fatalf("failed to get old state root, err: %v", err) + } + processRequest = &state.ProcessRequest{ + BatchNumber: processingCtx.BatchNumber, + OldStateRoot: oldStateRoot, + GlobalExitRoot: processingCtx.GlobalExitRoot, + Coinbase: processingCtx.Coinbase, + Timestamp: timestamp, + Caller: stateMetrics.SequencerCallerLabel, + } + currBatch = &WipBatch{ + globalExitRoot: processingCtx.GlobalExitRoot, + initialStateRoot: oldStateRoot, + stateRoot: oldStateRoot, + batchNumber: processingCtx.BatchNumber, + coinbase: processingCtx.Coinbase, + timestamp: timestamp, + remainingResources: getMaxRemainingResources(finalizer.batchConstraints), + } } else { - err = s.loadSequenceFromState(ctx) + err := finalizer.syncWithState(ctx, &batchNum) if err != nil { - log.Fatalf("failed to load sequence from the state, err: %v", err) + log.Fatalf("failed to sync with state, err: %v", err) } + currBatch = finalizer.batch + processRequest = &finalizer.processRequest } - go s.trackOldTxs(ctx) - tickerProcessTxs := time.NewTicker(s.cfg.WaitPeriodPoolIsEmpty.Duration) - tickerSendSequence := time.NewTicker(s.cfg.WaitPeriodSendSequence.Duration) - defer tickerProcessTxs.Stop() - defer tickerSendSequence.Stop() - go func() { - for { - s.tryToProcessTx(ctx, tickerProcessTxs) - } - }() - go func() { - for { - s.tryToSendSequence(ctx, tickerSendSequence) - } - }() - // Wait until context is done - <-ctx.Done() + return currBatch, processRequest } func (s *Sequencer) trackOldTxs(ctx context.Context) { ticker := time.NewTicker(s.cfg.FrequencyToCheckTxsForDelete.Duration) for { waitTick(ctx, ticker) + log.Infof("trying to get txs to delete from the pool...") txHashes, err := s.state.GetTxsOlderThanNL1Blocks(ctx, s.cfg.BlocksAmountForTxsToBeDeleted, nil) if err != nil { log.Errorf("failed to get txs hashes to delete, err: %v", err) continue } - err = s.pool.DeleteTxsByHashes(ctx, txHashes) + log.Infof("will try to delete %d redundant txs", len(txHashes)) + err = s.pool.DeleteTransactionsByHashes(ctx, txHashes) if err != nil { log.Errorf("failed to delete txs from the pool, err: %v", err) + continue } + log.Infof("deleted %d selected txs from the pool", len(txHashes)) } } @@ -141,123 +271,42 @@ func waitTick(ctx context.Context, ticker *time.Ticker) { func (s *Sequencer) isSynced(ctx context.Context) bool { lastSyncedBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) if err != nil && err != state.ErrNotFound { - log.Errorf("failed to get last synced batch, err: %v", err) + log.Errorf("failed to get last isSynced batch, err: %v", err) return false } + lastBatchNum, err := s.state.GetLastBatchNumber(ctx, nil) + if err != nil && err != state.ErrNotFound { + log.Errorf("failed to get last batch num, err: %v", err) + return false + } + if lastBatchNum > lastSyncedBatchNum { + return true + } lastEthBatchNum, err := s.etherman.GetLatestBatchNumber() if err != nil { log.Errorf("failed to get last eth batch, err: %v", err) return false } if lastSyncedBatchNum < lastEthBatchNum { - log.Infof("waiting for the state to be synced, lastSyncedBatchNum: %d, lastEthBatchNum: %d", lastSyncedBatchNum, lastEthBatchNum) + log.Infof("waiting for the state to be isSynced, lastSyncedBatchNum: %d, lastEthBatchNum: %d", lastSyncedBatchNum, lastEthBatchNum) return false } - return true -} - -func (s *Sequencer) loadSequenceFromState(ctx context.Context) error { - // Check if synchronizer is up to date - for !s.isSynced(ctx) { - log.Info("wait for synchronizer to sync last batch") - time.Sleep(time.Second) - } - // Revert reorged txs to pending - if err := s.pool.MarkReorgedTxsAsPending(ctx); err != nil { - return fmt.Errorf("failed to mark reorged txs as pending, err: %w", err) - } - // Get latest info from the state - lastBatch, err := s.state.GetLastBatch(ctx, nil) - if err != nil { - return fmt.Errorf("failed to get last batch, err: %w", err) - } - isClosed, err := s.state.IsBatchClosed(ctx, lastBatch.BatchNumber, nil) - if err != nil { - return fmt.Errorf("failed to check is batch closed or not, err: %w", err) - } - if isClosed { - dbTx, err := s.state.BeginStateTransaction(ctx) - if err != nil { - return fmt.Errorf("failed to begin state tx to open a batch, err: %w", err) - } - ger, err := s.getLatestGer(ctx, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - return fmt.Errorf( - "failed to rollback dbTx when getting last GER that gave err: %s. Rollback err: %s", - rollbackErr.Error(), err.Error(), - ) - } - return fmt.Errorf("failed to get latest global exit root, err: %w", err) - } - processingCtx := state.ProcessingContext{ - BatchNumber: lastBatch.BatchNumber + 1, - Coinbase: s.address, - Timestamp: time.Now(), - GlobalExitRoot: ger, - } - err = s.state.OpenBatch(ctx, processingCtx, dbTx) - if err != nil { - rollErr := dbTx.Rollback(ctx) - if rollErr != nil { - err = fmt.Errorf("failed to open a batch, err: %w. Rollback err: %v", err, rollErr) - } - return err - } - if err = dbTx.Commit(ctx); err != nil { - return fmt.Errorf("failed to commit a state tx to open a batch, err: %w", err) - } - s.sequenceInProgress = types.Sequence{ - GlobalExitRoot: processingCtx.GlobalExitRoot, - Timestamp: processingCtx.Timestamp.Unix(), - } - } else { - txs, err := s.state.GetTransactionsByBatchNumber(ctx, lastBatch.BatchNumber, nil) - if err != nil { - return fmt.Errorf("failed to get tx by batch number, err: %w", err) - } - s.sequenceInProgress = types.Sequence{ - GlobalExitRoot: lastBatch.GlobalExitRoot, - Timestamp: lastBatch.Timestamp.Unix(), - Txs: txs, - } - // TODO: execute to get state root and LER or change open/closed logic so we always store state root and LER and add an open flag - } - return nil - /* - TODO: deal with ongoing L1 txs - */ + return true } -func (s *Sequencer) createFirstBatch(ctx context.Context) { - log.Infof("starting sequencer with genesis batch") - processingCtx := state.ProcessingContext{ - BatchNumber: 1, - Coinbase: s.address, - Timestamp: time.Now(), - GlobalExitRoot: state.ZeroHash, - } - dbTx, err := s.state.BeginStateTransaction(ctx) - if err != nil { - log.Fatalf("failed to begin state transaction for opening a batch, err: %v", err) - } - err = s.state.OpenBatch(ctx, processingCtx, dbTx) - if err != nil { - if rollbackErr := dbTx.Rollback(ctx); rollbackErr != nil { - log.Fatalf( - "failed to rollback dbTx when opening batch that gave err: %v. Rollback err: %v", - rollbackErr, err, - ) - } - log.Fatalf("failed to open a batch, err: %v", err) - } - if err := dbTx.Commit(ctx); err != nil { - log.Fatalf("failed to commit dbTx when opening batch, err: %v", err) - } - s.sequenceInProgress = types.Sequence{ - GlobalExitRoot: processingCtx.GlobalExitRoot, - Timestamp: processingCtx.Timestamp.Unix(), - Txs: []ethTypes.Transaction{}, +func getMaxRemainingResources(constraints batchConstraints) state.BatchResources { + return state.BatchResources{ + ZKCounters: state.ZKCounters{ + CumulativeGasUsed: constraints.MaxCumulativeGasUsed, + UsedKeccakHashes: constraints.MaxKeccakHashes, + UsedPoseidonHashes: constraints.MaxPoseidonHashes, + UsedPoseidonPaddings: constraints.MaxPoseidonPaddings, + UsedMemAligns: constraints.MaxMemAligns, + UsedArithmetics: constraints.MaxArithmetics, + UsedBinaries: constraints.MaxBinaries, + UsedSteps: constraints.MaxSteps, + }, + Bytes: constraints.MaxBatchBytesSize, } } diff --git a/sequencer/sequencer_internal_test.go b/sequencer/sequencer_internal_test.go deleted file mode 100644 index d5683c23fa..0000000000 --- a/sequencer/sequencer_internal_test.go +++ /dev/null @@ -1,302 +0,0 @@ -package sequencer - -// TODO: commented, until process batch is implemented -//import ( -// "context" -// "math/big" -// "os" -// "strings" -// "testing" -// "time" -// -// "github.com/ethereum/go-ethereum/accounts/abi/bind" -// "github.com/ethereum/go-ethereum/common" -// "github.com/ethereum/go-ethereum/core/types" -// "github.com/ethereum/go-ethereum/crypto" -// "github.com/ethereum/go-ethereum/trie" -// cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" -// "github.com/0xPolygonHermez/zkevm-node/db" -// "github.com/0xPolygonHermez/zkevm-node/encoding" -// ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" -// "github.com/0xPolygonHermez/zkevm-node/pool" -// "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" -// "github.com/0xPolygonHermez/zkevm-node/pricegetter" -// "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker" -// "github.com/0xPolygonHermez/zkevm-node/state" -// "github.com/0xPolygonHermez/zkevm-node/state/tree" -// "github.com/0xPolygonHermez/zkevm-node/test/dbutils" -// "github.com/jackc/pgx/v4/pgxpool" -// "github.com/stretchr/testify/mock" -// "github.com/stretchr/testify/require" -//) -// -//const ( -// getPendingTxsLimit = 30 -// maxTxsInSequence = 5 -//) -// -//type stateTestInterface interface { -// stateInterface -// GetLastBatch(ctx context.Context, isVirtual bool, txBundleID string) (*state.Batch, error) -// GetNonce(ctx context.Context, address common.Address, batchNumber uint64, txBundleID string) (uint64, error) -// GetBalance(ctx context.Context, address common.Address, batchNumber uint64, txBundleID string) (*big.Int, error) -// NewGenesisBatchProcessor(genesisStateRoot []byte, txBundleID string) (*state.BatchProcessor, error) -// SetLastBatchNumberSeenOnEthereum(ctx context.Context, batchNumber uint64, txBundleID string) error -// SetGenesis(ctx context.Context, genesis state.Genesis, txBundleID string) error -//} -// -//var ( -// dbCfg = dbutils.NewConfigFromEnv() -// stateDB *pgxpool.Pool -// testState stateTestInterface -// seqCfg Config -// pl *pool.Pool -// -// genesisHash common.Hash -// txs []*types.Transaction -// -// senderPrivateKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" -// addr = common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b") -// consolidatedTxHash = common.HexToHash("0x125714bb4db48757007fff2671b37637bbfd6d47b3a4757ebbd0c5222984f905") -// maticCollateral = big.NewInt(1000000000000000000) -// lastBatchNumberSeen uint64 = 1 -//) -// -//var stateCfg = state.Config{ -// MaxCumulativeGasUsed: 800000, -//} -// -//func setUpBlock(ctx context.Context, t *testing.T) { -// blockHash := common.HexToHash("0x65b4699dda5f7eb4519c730e6a48e73c90d2b1c8efcd6a6abdfd28c3b8e7d7d9") -// -// block := &state.Block{ -// BlockNumber: 1, -// BlockHash: blockHash, -// ParentHash: genesisHash, -// ReceivedAt: time.Now(), -// } -// -// _, err := stateDB.Exec(ctx, "INSERT INTO state.block (block_num, block_hash, parent_hash, received_at) VALUES ($1, $2, $3, $4)", -// block.BlockNumber, block.BlockHash.Bytes(), block.ParentHash.Bytes(), block.ReceivedAt) -// if err != nil { -// require.NoError(t, err) -// } -//} -// -//func setUpBatch(ctx context.Context, t *testing.T) { -// receivedAt := time.Now().Add(time.Duration(-5) * time.Minute) -// consolidatedAt := time.Now() -// batch := &state.Batch{ -// BlockNumber: 1, -// Sequencer: addr, -// Aggregator: addr, -// ConsolidatedTxHash: consolidatedTxHash, -// Header: &types.Header{Number: big.NewInt(1)}, -// Uncles: nil, -// RawTxsData: nil, -// MaticCollateral: maticCollateral, -// ReceivedAt: receivedAt, -// ConsolidatedAt: &consolidatedAt, -// ChainID: big.NewInt(1000), -// GlobalExitRoot: common.Hash{}, -// } -// bp, err := testState.NewGenesisBatchProcessor(nil, "") -// if err != nil { -// require.NoError(t, err) -// } -// -// err = bp.ProcessBatch(ctx, batch) -// if err != nil { -// require.NoError(t, err) -// } -//} -// -//func TestMain(m *testing.M) { -// var err error -// -// if err := dbutils.InitOrReset(dbCfg); err != nil { -// panic(err) -// } -// -// stateDB, err = db.NewSQLDB(dbCfg) -// if err != nil { -// panic(err) -// } -// defer stateDB.Close() -// -// store := tree.NewPostgresStore(stateDB) -// mt := tree.NewMerkleTree(store, tree.DefaultMerkleTreeArity) -// scCodeStore := tree.NewPostgresSCCodeStore(stateDB) -// testState = state.NewState(stateCfg, state.NewPostgresStorage(stateDB), tree.NewStateTree(mt, scCodeStore)) -// -// seqCfg = Config{ -// WaitPeriodPoolIsEmpty: cfgTypes.NewDuration(time.Second), -// LastL1InteractionTimeMaxWaitPeriod: cfgTypes.NewDuration(60 * time.Second), -// WaitBlocksToUpdateGER: 10, -// MaxTimeForBatchToBeOpen: cfgTypes.NewDuration(60 * time.Second), -// ProfitabilityChecker: profitabilitychecker.Config{SendBatchesEvenWhenNotProfitable: true}, -// } -// -// s, err := pgpoolstorage.NewPostgresPoolStorage(dbCfg) -// if err != nil { -// panic(err) -// } -// pl = pool.NewPool(s, testState, stateCfg.L2GlobalExitRootManagerAddr) -// -// genesisBlock := types.NewBlock(&types.Header{Number: big.NewInt(0)}, []*types.Transaction{}, []*types.Header{}, []*types.Receipt{}, &trie.StackTrie{}) -// genesisBlock.ReceivedAt = time.Now() -// genesisHash = genesisBlock.Hash() -// balance, _ := big.NewInt(0).SetString("1000000000000000000000", encoding.Base10) -// genesis := state.Genesis{ -// Block: genesisBlock, -// Balances: map[common.Address]*big.Int{ -// common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D"): balance, -// }, -// } -// -// err = testState.SetLastBatchNumberSeenOnEthereum(context.Background(), lastBatchNumberSeen, "") -// if err != nil { -// panic(err) -// } -// ctx := context.Background() -// _, err = stateDB.Exec(ctx, "DELETE FROM state.block") -// if err != nil { -// panic(err) -// } -// -// err = testState.SetGenesis(ctx, genesis, "") -// if err != nil { -// panic(err) -// } -// privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(senderPrivateKey, "0x")) -// if err != nil { -// panic(err) -// } -// -// auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1000)) -// if err != nil { -// panic(err) -// } -// -// for i := 0; i < 10; i++ { -// tx := types.NewTransaction(uint64(i), common.Address{}, big.NewInt(10), uint64(21000), big.NewInt(10), []byte{}) -// signedTx, err := auth.Signer(auth.From, tx) -// if err != nil { -// panic(err) -// } -// ctx := context.Background() -// if err := pl.AddTx(ctx, *signedTx); err != nil { -// panic(err) -// } -// txs = append(txs, signedTx) -// } -// -// result := m.Run() -// os.Exit(result) -//} -// -//func TestSequencerBaseFlow(t *testing.T) { -// // set up prerequisites -// txManager := new(txmanagerMock) -// ctx := context.Background() -// setUpBlock(ctx, t) -// setUpBatch(ctx, t) -// ethMan := new(ethermanMock) -// gasCostMin := big.NewInt(0) -// gasCostMax, _ := new(big.Int).SetString("1000000000000000000", 10) -// ethMan.On("EstimateGasSequenceBatches", mock.Anything).Return(gasCostMax, nil) -// ethMan.On("GetSendSequenceFee").Return(gasCostMin, nil) -// -// // get pending txs to build sequences to send, so test could check if variables are equal -// pendTxs, err := pl.GetPendingTxs(ctx, false, getPendingTxsLimit) -// require.NoError(t, err) -// sequencesToSent := make([]ethmanTypes.Sequence, 5) -// for i := 0; i < 2; i++ { -// for k := maxTxsInSequence * i; k < maxTxsInSequence*(i+1); k++ { -// sequencesToSent[i].Txs = append(sequencesToSent[i].Txs, pendTxs[k].Transaction) -// } -// } -// -// txManager.On("SequenceBatches", mock.MatchedBy(func(sequences []ethmanTypes.Sequence) bool { -// res := true -// for i := 0; i < len(sequences); i++ { -// for k := 0; k < len(sequences[i].Txs); k++ { -// res = res && sequences[i].Txs[k].Hash() == sequencesToSent[i].Txs[k].Hash() -// } -// } -// return res -// })).Return(nil, nil) -// -// pg, err := pricegetter.NewClient(pricegetter.Config{ -// Type: pricegetter.DefaultType, -// DefaultPrice: pricegetter.TokenPrice{Float: new(big.Float).SetInt64(2000)}, -// }) -// require.NoError(t, err) -// seq, err := New(seqCfg, pl, testState, ethMan, pg, txManager) -// require.NoError(t, err) -// require.Equal(t, 10, len(pendTxs)) -// -// // try to process transactions that should fit in one sequence -// ticker := time.NewTicker(seqCfg.WaitPeriodPoolIsEmpty.Duration) -// for i := 0; i < maxTxsInSequence; i++ { -// seq.tryToProcessTx(ctx, ticker) -// } -// -// // check, that all requested txs are selected and there are 5 txs in sequence in progress -// pendTxs, err = pl.GetPendingTxs(ctx, false, getPendingTxsLimit) -// require.NoError(t, err) -// require.Equal(t, 5, len(pendTxs)) -// require.Equal(t, maxTxsInSequence, len(seq.sequenceInProgress.Txs)) -// require.Equal(t, 0, len(seq.closedSequences)) -// -// // checks that if seq meets WaitBlocksToUpdateGER condition, it will close a sequence -// seq.cfg.MaxTimeForBatchToBeOpen = cfgTypes.NewDuration(0) -// seq.tryToProcessTx(ctx, ticker) -// pendTxs, err = pl.GetPendingTxs(ctx, false, getPendingTxsLimit) -// require.NoError(t, err) -// -// // check, that after processing one tx, only 4 pending txs left in the pool, -// // seq have 1 tx in sequence in progress and 1 closed sequence -// require.Equal(t, 4, len(pendTxs)) -// require.Equal(t, 1, len(seq.sequenceInProgress.Txs)) -// require.Equal(t, 1, len(seq.closedSequences)) -// require.Equal(t, maxTxsInSequence, len(seq.closedSequences[0].Txs)) -// -// // return config param back -// seq.cfg.MaxTimeForBatchToBeOpen = cfgTypes.NewDuration(10 * time.Second) -// -// for i := 0; i < 4; i++ { -// seq.tryToProcessTx(ctx, ticker) -// } -// -// // set config params that way, that txs will be selected and sent to ethereum -// seq.cfg.LastL1InteractionTimeMaxWaitPeriod = cfgTypes.NewDuration(0) -// seq.cfg.MaxTimeForBatchToBeOpen = cfgTypes.NewDuration(0) -// seq.tryToProcessTx(ctx, ticker) -// -// // checks, that after processing there is no pending txs left, no txs in sequence in progress -// // and no pending closed sequences -// pendTxs, err = pl.GetPendingTxs(ctx, false, getPendingTxsLimit) -// require.NoError(t, err) -// require.Equal(t, 0, len(pendTxs)) -// require.Equal(t, 0, len(seq.sequenceInProgress.Txs)) -// require.Equal(t, 0, len(seq.closedSequences)) -// -// txManager.AssertNumberOfCalls(t, "SequenceBatches", 1) -// cleanUpBatches(ctx, t) -// cleanUpBlocks(ctx, t) -//} -// -//func cleanUpBatches(ctx context.Context, t *testing.T) { -// _, err := stateDB.Exec(ctx, "DELETE FROM state.batch WHERE block_num = $1", 1) -// if err != nil { -// require.NoError(t, err) -// } -//} -// -//func cleanUpBlocks(ctx context.Context, t *testing.T) { -// _, err := stateDB.Exec(ctx, "DELETE FROM state.block WHERE block_num = $1", 1) -// if err != nil { -// require.NoError(t, err) -// } -//} diff --git a/sequencer/sequencer_test.go b/sequencer/sequencer_test.go deleted file mode 100644 index ca51c696e9..0000000000 --- a/sequencer/sequencer_test.go +++ /dev/null @@ -1,265 +0,0 @@ -package sequencer - -import ( - "context" - "fmt" - "io/ioutil" - "math/big" - "testing" - "time" - - "github.com/0xPolygonHermez/zkevm-node/config/types" - "github.com/0xPolygonHermez/zkevm-node/db" - ethman "github.com/0xPolygonHermez/zkevm-node/etherman" - "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" - "github.com/0xPolygonHermez/zkevm-node/gasprice" - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/pricegetter" - "github.com/0xPolygonHermez/zkevm-node/sequencer/profitabilitychecker" - st "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" - "github.com/0xPolygonHermez/zkevm-node/test/dbutils" - "github.com/0xPolygonHermez/zkevm-node/test/testutils" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" -) - -func TestSequenceTooBig(t *testing.T) { - // before running: - // make run-db - // make run-network - // make run-zkprover - - const ( - CONFIG_MAX_GAS_PER_SEQUENCE = 200000 - CONFIG_ENCRYPTION_KEY_FILE_PATH = "./../test/test.keystore" - CONFIG_ENCRYPTION_KEY_PASSWORD = "testonly" - CONFIG_CHAIN_ID = 1337 - CONFIG_ETH_URL = "http://localhost:8545" - - CONFIG_NAME_POE = "poe" - CONFIG_NAME_MATIC = "matic" - CONFIG_NAME_GER = "ger" - ) - - var ( - CONFIG_ADDRESSES = map[string]common.Address{ - CONFIG_NAME_POE: common.HexToAddress("0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"), // <= PoE - CONFIG_NAME_MATIC: common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3"), // <= Matic - CONFIG_NAME_GER: common.HexToAddress("0xae4bb80be56b819606589de61d5ec3b522eeb032"), // <= GER - } - CONFIG_DB_STATE = db.Config{ - User: "state_user", - Password: "state_password", - Name: "state_db", - Host: "localhost", - Port: "5432", - EnableLog: false, - MaxConns: 200, - } - CONFIG_DB_POOL = db.Config{ - User: "pool_user", - Password: "pool_password", - Name: "pool_db", - Host: "localhost", - Port: "5433", - EnableLog: false, - MaxConns: 200, - } - CONFIG_EXECUTOR_URL = fmt.Sprintf("%s:50071", testutils.GetEnv("ZKPROVER_URI", "localhost")) - ) - type TestCase struct { - Input []int // slice of batch sizes - Output int // split into N sequences - - } - - var testcases = []TestCase{ - { - Input: []int{ - 1000, - 500, - }, - Output: 2, // two sequences (of 1 batch each) fit inside - }, - - { - Input: []int{ - 1, - }, - Output: 1, // only one sequence fits - }, - { - Input: []int{ - 100000000, - 1000000, - 1000, - 100, - 1, - }, - Output: 2, // only two sequences fit inside - }, - { - Input: []int{ - 1, 1, 1, 1, - }, - Output: 2, // all sequences fit inside - }, - } - ctx := context.Background() - - keystoreEncrypted, err := ioutil.ReadFile(CONFIG_ENCRYPTION_KEY_FILE_PATH) - require.NoError(t, err) - key, err := keystore.DecryptKey(keystoreEncrypted, CONFIG_ENCRYPTION_KEY_PASSWORD) - require.NoError(t, err) - - auth, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, big.NewInt(CONFIG_CHAIN_ID)) - require.NoError(t, err) - // eth_man, _, _, _, err := ethman.NewSimulatedEtherman(ethman.Config{}, auth) - eth_man, err := ethman.NewClient(ethman.Config{ - URL: CONFIG_ETH_URL, - }, auth, CONFIG_ADDRESSES[CONFIG_NAME_POE], CONFIG_ADDRESSES[CONFIG_NAME_MATIC], CONFIG_ADDRESSES[CONFIG_NAME_GER]) - - require.NoError(t, err) - - const decimals = 1000000000000000000 - amount := big.NewFloat(10000000000000000) - amountInWei := new(big.Float).Mul(amount, big.NewFloat(decimals)) - amountB := new(big.Int) - amountInWei.Int(amountB) - - _, err = eth_man.ApproveMatic(amountB, CONFIG_ADDRESSES[CONFIG_NAME_POE]) - require.NoError(t, err) - - pg, err := pricegetter.NewClient(pricegetter.Config{ - Type: "default", - }) - require.NoError(t, err) - - err = dbutils.InitOrResetState(CONFIG_DB_STATE) - require.NoError(t, err) - - err = dbutils.InitOrResetPool(CONFIG_DB_POOL) - require.NoError(t, err) - - poolDb, err := pgpoolstorage.NewPostgresPoolStorage(CONFIG_DB_POOL) - require.NoError(t, err) - - sqlStateDB, err := db.NewSQLDB(CONFIG_DB_STATE) - require.NoError(t, err) - - stateDb := st.NewPostgresStorage(sqlStateDB) - executorClient, _, _ := executor.NewExecutorClient(ctx, executor.Config{ - URI: CONFIG_EXECUTOR_URL, - }) - stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, merkletree.Config{ - URI: CONFIG_EXECUTOR_URL, - }) - stateTree := merkletree.NewStateTree(stateDBClient) - - stateCfg := st.Config{ - MaxCumulativeGasUsed: 30000000, - ChainID: CONFIG_CHAIN_ID, - } - - state := st.NewState(stateCfg, stateDb, executorClient, stateTree) - - pool := pool.NewPool(poolDb, state, CONFIG_ADDRESSES[CONFIG_NAME_GER], big.NewInt(CONFIG_CHAIN_ID).Uint64()) - ethtxmanager := ethtxmanager.New(ethtxmanager.Config{}, eth_man) - gpe := gasprice.NewDefaultEstimator(gasprice.Config{ - Type: gasprice.DefaultType, - DefaultGasPriceWei: 1000000000, - }, pool) - seq, err := New(Config{ - MaxSequenceSize: MaxSequenceSize{Int: big.NewInt(CONFIG_MAX_GAS_PER_SEQUENCE)}, - LastBatchVirtualizationTimeMaxWaitPeriod: types.NewDuration(1 * time.Second), - ProfitabilityChecker: profitabilitychecker.Config{ - SendBatchesEvenWhenNotProfitable: true, - }, - }, pool, state, eth_man, pg, ethtxmanager, gpe) - require.NoError(t, err) - - // generate fake data - - mainnetExitRoot := common.HexToHash("caffe") - rollupExitRoot := common.HexToHash("bead") - - if _, err := stateDb.Exec(ctx, "DELETE FROM state.block"); err != nil { - t.Fail() - } - if _, err := stateDb.Exec(ctx, "DELETE FROM state.batch"); err != nil { - t.Fail() - } - if _, err := stateDb.Exec(ctx, "DELETE FROM state.exit_root"); err != nil { - t.Fail() - } - - const sqlAddBlock = "INSERT INTO state.block (block_num, received_at, block_hash) VALUES ($1, $2, $3)" - _, err = stateDb.Exec(ctx, sqlAddBlock, 1, time.Now(), "") - require.NoError(t, err) - - _, err = stateDb.Exec(ctx, sqlAddBlock, 2, time.Now(), "") // for use in lastVirtualized time - require.NoError(t, err) - - const sqlAddExitRoots = "INSERT INTO state.exit_root (block_num, global_exit_root, mainnet_exit_root, rollup_exit_root, global_exit_root_num) VALUES ($1, $2, $3, $4, $5)" - _, err = stateDb.Exec(ctx, sqlAddExitRoots, 1, common.Address{}, mainnetExitRoot, rollupExitRoot, 3) - require.NoError(t, err) - - for _, testCase := range testcases { - innerDbTx, err := state.BeginStateTransaction(ctx) - require.NoError(t, err) - err = dbutils.InitOrResetState(CONFIG_DB_STATE) - require.NoError(t, err) - - err = dbutils.InitOrResetPool(CONFIG_DB_POOL) - require.NoError(t, err) - - if _, err := stateDb.Exec(ctx, "DELETE FROM state.block"); err != nil { - t.Fail() - } - if _, err := stateDb.Exec(ctx, "DELETE FROM state.batch"); err != nil { - t.Fail() - } - - for i := 0; i < len(testCase.Input); i++ { - fmt.Printf("\niteration: [%d]: %d\n", testCase.Output, testCase.Input[i]) - - payload := make([]byte, testCase.Input[i]) // 10mb - - _, err = stateDb.Exec(ctx, "INSERT INTO state.batch (batch_num, global_exit_root, local_exit_root, state_root, timestamp, coinbase, raw_txs_data) VALUES ($1, $2, $3, $4, $5, $6, $7)", - i+1, - common.Address{}.String(), - common.Hash{}.String(), - common.Hash{}.String(), - time.Unix(9, 0).UTC(), - common.HexToAddress("").String(), - payload, - ) - require.NoError(t, err) - } - - //needed for completion: wip batch - - _, err = stateDb.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES ($1)", - len(testCase.Input)+1, - ) - - require.NoError(t, err) - - // make L2 equivalences - - err = innerDbTx.Commit(ctx) - require.NoError(t, err) - - sequences, err := seq.getSequencesToSend(ctx) - require.NoError(t, err) - - fmt.Printf("%+v", sequences) - - require.Equal(t, testCase.Output, len(sequences)) - } -} diff --git a/sequencer/sequencesender.go b/sequencer/sequencesender.go deleted file mode 100644 index 7a274ab9c7..0000000000 --- a/sequencer/sequencesender.go +++ /dev/null @@ -1,218 +0,0 @@ -package sequencer - -import ( - "context" - "errors" - "fmt" - "math/big" - "strings" - "time" - - "github.com/0xPolygonHermez/zkevm-node/etherman/types" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/core" - ethtypes "github.com/ethereum/go-ethereum/core/types" -) - -func (s *Sequencer) tryToSendSequence(ctx context.Context, ticker *time.Ticker) { - // Check if synchronizer is up to date - if !s.isSynced(ctx) { - log.Info("wait for synchronizer to sync last batch") - waitTick(ctx, ticker) - return - } - - // Check if should send sequence to L1 - log.Infof("getting sequences to send") - sequences, err := s.getSequencesToSend(ctx) - if err != nil || len(sequences) == 0 { - if err != nil { - log.Errorf("error getting sequences: %v", err) - } else { - log.Info("waiting for sequences to be worth sending to L1") - } - waitTick(ctx, ticker) - return - } - - lastVirtualBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) - if err != nil { - log.Errorf("failed to get last virtual batch num, err: %w", err) - return - } - - // Send sequences to L1 - log.Infof( - "sending sequences to L1. From batch %d to batch %d", - lastVirtualBatchNum+1, lastVirtualBatchNum+uint64(len(sequences)), - ) - s.txManager.SequenceBatches(sequences) -} - -// getSequencesToSend generates an array of sequences to be send to L1. -// If the array is empty, it doesn't necessarily mean that there are no sequences to be sent, -// it could be that it's not worth it to do so yet. -func (s *Sequencer) getSequencesToSend(ctx context.Context) ([]types.Sequence, error) { - lastVirtualBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) - if err != nil { - return nil, fmt.Errorf("failed to get last virtual batch num, err: %w", err) - } - - currentBatchNumToSequence := lastVirtualBatchNum + 1 - sequences := []types.Sequence{} - var estimatedGas uint64 - - var tx *ethtypes.Transaction - - // Add sequences until too big for a single L1 tx or last batch is reached - for { - // Check if batch is closed - isClosed, err := s.state.IsBatchClosed(ctx, currentBatchNumToSequence, nil) - if err != nil { - return nil, err - } - if !isClosed { - // Reached current (WIP) batch - break - } - // Add new sequence - batch, err := s.state.GetBatchByNumber(ctx, currentBatchNumToSequence, nil) - if err != nil { - return nil, err - } - txs, err := s.state.GetTransactionsByBatchNumber(ctx, currentBatchNumToSequence, nil) - if err != nil { - return nil, err - } - sequences = append(sequences, types.Sequence{ - GlobalExitRoot: batch.GlobalExitRoot, - Timestamp: batch.Timestamp.Unix(), - // ForceBatchesNum: TODO, - Txs: txs, - }) - - // Check if can be send - tx, err = s.etherman.EstimateGasSequenceBatches(sequences) - - if err == nil && new(big.Int).SetUint64(tx.Gas()).Cmp(s.cfg.MaxSequenceSize.Int) >= 1 { - log.Infof("oversized Data on TX hash %s (%d > %d)", tx.Hash(), tx.Gas(), s.cfg.MaxSequenceSize) - err = core.ErrOversizedData - } - - if err != nil { - sequences, err = s.handleEstimateGasSendSequenceErr(ctx, sequences, currentBatchNumToSequence, err) - if sequences != nil { - // Handling the error gracefully, re-processing the sequence as a sanity check - _, err = s.etherman.EstimateGasSequenceBatches(sequences) - return sequences, err - } - return sequences, err - } - estimatedGas = tx.Gas() - - // Increase batch num for next iteration - currentBatchNumToSequence++ - } - - // Reached latest batch. Decide if it's worth to send the sequence, or wait for new batches - if len(sequences) == 0 { - log.Info("no batches to be sequenced") - return nil, nil - } - - lastBatchVirtualizationTime, err := s.state.GetTimeForLatestBatchVirtualization(ctx, nil) - if err != nil && !errors.Is(err, state.ErrNotFound) { - log.Warnf("failed to get last l1 interaction time, err: %v. Sending sequences as a conservative approach", err) - return sequences, nil - } - if lastBatchVirtualizationTime.Before(time.Now().Add(-s.cfg.LastBatchVirtualizationTimeMaxWaitPeriod.Duration)) { - // check profitability - if s.checker.IsSendSequencesProfitable(new(big.Int).SetUint64(estimatedGas), sequences) { - log.Info("sequence should be sent to L1, because too long since didn't send anything to L1") - return sequences, nil - } - } - - log.Info("not enough time has passed since last batch was virtualized, and the sequence could be bigger") - return nil, nil -} - -// handleEstimateGasSendSequenceErr handles an error on the estimate gas. It will return: -// nil, error: impossible to handle gracefully -// sequence, nil: handled gracefully. Potentially manipulating the sequences -// nil, nil: a situation that requires waiting -func (s *Sequencer) handleEstimateGasSendSequenceErr( - ctx context.Context, - sequences []types.Sequence, - currentBatchNumToSequence uint64, - err error, -) ([]types.Sequence, error) { - // Insufficient allowance - if strings.Contains(err.Error(), errInsufficientAllowance) { - return nil, err - } - - if isDataForEthTxTooBig(err) { - if len(sequences) == 1 { - // TODO: gracefully handle this situation by creating an L2 reorg - log.Fatalf( - "BatchNum %d is too big to be sent to L1, even when it's the only item in the sequence: %v", - currentBatchNumToSequence, err, - ) - } - // Remove the latest item and send the sequences - log.Infof( - "Done building sequences, selected batches to %d. Batch %d caused the L1 tx to be too big", - currentBatchNumToSequence, currentBatchNumToSequence+1, - ) - sequences = sequences[:len(sequences)-1] - return sequences, nil - } - - // while estimating gas a new block is not created and the POE SC may return - // an error regarding timestamp verification, this must be handled - if strings.Contains(err.Error(), errTimestampMustBeInsideRange) { - // query the sc about the value of its lastTimestamp variable - lastTimestamp, err := s.etherman.GetLastBatchTimestamp() - if err != nil { - return nil, err - } - // check POE SC lastTimestamp against sequences' one - for _, seq := range sequences { - if seq.Timestamp < int64(lastTimestamp) { - // TODO: gracefully handle this situation by creating an L2 reorg - log.Fatalf("sequence timestamp %d is < POE SC lastTimestamp %d", seq.Timestamp, lastTimestamp) - } - lastTimestamp = uint64(seq.Timestamp) - } - blockTimestamp, err := s.etherman.GetLatestBlockTimestamp(ctx) - if err != nil { - log.Error("error getting block timestamp: ", err) - } - log.Debugf("block.timestamp: %d is smaller than seq.Timestamp: %d. A new block must be mined in L1 before the gas can be estimated.", blockTimestamp, sequences[0].Timestamp) - return nil, nil - } - - // Unknown error - if len(sequences) == 1 { - // TODO: gracefully handle this situation by creating an L2 reorg - log.Fatalf( - "Error when estimating gas for BatchNum %d (alone in the sequences): %v", - currentBatchNumToSequence, err, - ) - } - // Remove the latest item and send the sequences - log.Infof( - "Done building sequences, selected batches to %d. Batch %d excluded due to unknown error: %v", - currentBatchNumToSequence, currentBatchNumToSequence+1, err, - ) - sequences = sequences[:len(sequences)-1] - return sequences, nil -} - -func isDataForEthTxTooBig(err error) bool { - return strings.Contains(err.Error(), errGasRequiredExceedsAllowance) || - errors.Is(err, core.ErrOversizedData) || - strings.Contains(err.Error(), errContentLengthTooLarge) -} diff --git a/sequencer/txtracker.go b/sequencer/txtracker.go new file mode 100644 index 0000000000..781bfeb4e7 --- /dev/null +++ b/sequencer/txtracker.go @@ -0,0 +1,157 @@ +package sequencer + +import ( + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// TxTracker is a struct that contains all the tx data needed to be managed by the worker +type TxTracker struct { + Hash common.Hash + HashStr string + From common.Address + FromStr string + Nonce uint64 + Gas uint64 // To check if it fits into a batch + GasPrice *big.Int + Cost *big.Int // Cost = Amount + Benefit + Benefit *big.Int // GasLimit * GasPrice + BatchResources state.BatchResources // To check if it fits into a batch + Efficiency float64 + RawTx []byte + ReceivedAt time.Time // To check if it has been in the efficiency list for too long + IP string // IP of the tx sender + FailedReason *string // FailedReason is the reason why the tx failed, if it failed + constraints batchConstraintsFloat64 + weightMultipliers batchResourceWeightMultipliers + resourceCostMultiplier float64 + totalWeight float64 +} + +// batchResourceWeightMultipliers is a struct that contains the weight multipliers for each resource +type batchResourceWeightMultipliers struct { + cumulativeGasUsed float64 + arithmetics float64 + binaries float64 + keccakHashes float64 + memAligns float64 + poseidonHashes float64 + poseidonPaddings float64 + steps float64 + batchBytesSize float64 +} + +// batchConstraints represents the constraints for a batch in float64 +type batchConstraintsFloat64 struct { + maxTxsPerBatch float64 + maxBatchBytesSize float64 + maxCumulativeGasUsed float64 + maxKeccakHashes float64 + maxPoseidonHashes float64 + maxPoseidonPaddings float64 + maxMemAligns float64 + maxArithmetics float64 + maxBinaries float64 + maxSteps float64 +} + +// newTxTracker creates and inti a TxTracker +func newTxTracker(tx types.Transaction, counters state.ZKCounters, constraints batchConstraintsFloat64, weights batchResourceWeights, resourceCostMultiplier float64, ip string) (*TxTracker, error) { + addr, err := state.GetSender(tx) + if err != nil { + return nil, err + } + + totalWeight := float64(weights.WeightArithmetics + weights.WeightBatchBytesSize + weights.WeightBinaries + weights.WeightCumulativeGasUsed + + weights.WeightKeccakHashes + weights.WeightMemAligns + weights.WeightPoseidonHashes + weights.WeightPoseidonPaddings + weights.WeightSteps) + rawTx, err := state.EncodeTransactions([]types.Transaction{tx}) + if err != nil { + return nil, err + } + txTracker := &TxTracker{ + Hash: tx.Hash(), + HashStr: tx.Hash().String(), + From: addr, + FromStr: addr.String(), + Nonce: tx.Nonce(), + Gas: tx.Gas(), + GasPrice: tx.GasPrice(), + Cost: tx.Cost(), + Benefit: new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()), + BatchResources: state.BatchResources{ + Bytes: tx.Size(), + ZKCounters: counters, + }, + Efficiency: 0, + RawTx: rawTx, + ReceivedAt: time.Now(), + IP: ip, + constraints: constraints, + weightMultipliers: calculateWeightMultipliers(weights, totalWeight), + resourceCostMultiplier: resourceCostMultiplier, + totalWeight: totalWeight, + } + txTracker.calculateEfficiency(constraints, weights) + + return txTracker, nil +} + +// updateZKCounters updates the counters of the tx and recalculates the tx efficiency + +func (tx *TxTracker) updateZKCounters(counters state.ZKCounters, constraints batchConstraintsFloat64, weights batchResourceWeights) { + tx.BatchResources.ZKCounters = counters + tx.calculateEfficiency(constraints, weights) +} + +// calculateEfficiency calculates the tx efficiency +func (tx *TxTracker) calculateEfficiency(constraints batchConstraintsFloat64, weights batchResourceWeights) { + totalWeight := float64(weights.WeightArithmetics + weights.WeightBatchBytesSize + weights.WeightBinaries + weights.WeightCumulativeGasUsed + + weights.WeightKeccakHashes + weights.WeightMemAligns + weights.WeightPoseidonHashes + weights.WeightPoseidonPaddings + weights.WeightSteps) + + // TODO: Optmize tx.Efficiency calculation (precalculate constansts values) + // TODO: Evaluate avoid type conversion (performance impact?) + resourceCost := (float64(tx.BatchResources.ZKCounters.CumulativeGasUsed)/constraints.maxCumulativeGasUsed)*float64(weights.WeightCumulativeGasUsed)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedArithmetics)/constraints.maxArithmetics)*float64(weights.WeightArithmetics)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedBinaries)/constraints.maxBinaries)*float64(weights.WeightBinaries)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedKeccakHashes)/constraints.maxKeccakHashes)*float64(weights.WeightKeccakHashes)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedMemAligns)/constraints.maxMemAligns)*float64(weights.WeightMemAligns)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedPoseidonHashes)/constraints.maxPoseidonHashes)*float64(weights.WeightPoseidonHashes)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedPoseidonPaddings)/constraints.maxPoseidonPaddings)*float64(weights.WeightPoseidonPaddings)/totalWeight + + (float64(tx.BatchResources.ZKCounters.UsedSteps)/constraints.maxSteps)*float64(weights.WeightSteps)/totalWeight + + (float64(tx.BatchResources.Bytes)/constraints.maxBatchBytesSize)*float64(weights.WeightBatchBytesSize)/totalWeight //Meto config + + resourceCost = resourceCost * tx.resourceCostMultiplier + + var eff *big.Float + + ben := big.NewFloat(0).SetInt(tx.Benefit) + rc := big.NewFloat(0).SetFloat64(resourceCost) + eff = big.NewFloat(0).Quo(ben, rc) + + var accuracy big.Accuracy + tx.Efficiency, accuracy = eff.Float64() + log.Infof("CalculateEfficiency(%f) for tx(%s)", tx.Efficiency, tx.Hash.String()) + if accuracy != big.Exact { + log.Errorf("CalculateEfficiency accuracy warning (%s). Calculated=%s Assigned=%f", accuracy.String(), eff.String(), tx.Efficiency) + } +} + +// calculateWeightMultipliers calculates the weight multipliers for each resource +func calculateWeightMultipliers(weights batchResourceWeights, totalWeight float64) batchResourceWeightMultipliers { + return batchResourceWeightMultipliers{ + cumulativeGasUsed: float64(weights.WeightCumulativeGasUsed) / totalWeight, + arithmetics: float64(weights.WeightArithmetics) / totalWeight, + binaries: float64(weights.WeightBinaries) / totalWeight, + keccakHashes: float64(weights.WeightKeccakHashes) / totalWeight, + memAligns: float64(weights.WeightMemAligns) / totalWeight, + poseidonHashes: float64(weights.WeightPoseidonHashes) / totalWeight, + poseidonPaddings: float64(weights.WeightPoseidonPaddings) / totalWeight, + steps: float64(weights.WeightSteps) / totalWeight, + batchBytesSize: float64(weights.WeightBatchBytesSize) / totalWeight, + } +} diff --git a/sequencer/txtracker_test.go b/sequencer/txtracker_test.go new file mode 100644 index 0000000000..a238ebede4 --- /dev/null +++ b/sequencer/txtracker_test.go @@ -0,0 +1,100 @@ +package sequencer + +import ( + "fmt" + "math/big" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/stretchr/testify/assert" +) + +type efficiencyCalcTestCase struct { + Name string + benefit int64 + counters state.ZKCounters + usedBytes uint64 + expectedResult float64 +} + +func TestTxTrackerEfficiencyCalculation(t *testing.T) { + // Init ZKEVM resourceCostWeight values + rcWeigth := batchResourceWeights{} + rcWeigth.WeightCumulativeGasUsed = 1 + rcWeigth.WeightArithmetics = 1 + rcWeigth.WeightBinaries = 1 + rcWeigth.WeightKeccakHashes = 1 + rcWeigth.WeightMemAligns = 1 + rcWeigth.WeightPoseidonHashes = 1 + rcWeigth.WeightPoseidonPaddings = 1 + rcWeigth.WeightSteps = 1 + rcWeigth.WeightBatchBytesSize = 2 + + // Init ZKEVM resourceCostMax values + rcMax := batchConstraintsFloat64{} + rcMax.maxCumulativeGasUsed = 10 + rcMax.maxArithmetics = 10 + rcMax.maxBinaries = 10 + rcMax.maxKeccakHashes = 10 + rcMax.maxMemAligns = 10 + rcMax.maxPoseidonHashes = 10 + rcMax.maxPoseidonPaddings = 10 + rcMax.maxSteps = 10 + rcMax.maxBatchBytesSize = 10 + + totalWeight := float64(rcWeigth.WeightArithmetics + rcWeigth.WeightBatchBytesSize + rcWeigth.WeightBinaries + rcWeigth.WeightCumulativeGasUsed + + rcWeigth.WeightKeccakHashes + rcWeigth.WeightMemAligns + rcWeigth.WeightPoseidonHashes + rcWeigth.WeightPoseidonPaddings + rcWeigth.WeightSteps) + + testCases := []efficiencyCalcTestCase{ + { + Name: "Using all of the resources", + benefit: 1000000, + counters: state.ZKCounters{CumulativeGasUsed: 10, UsedKeccakHashes: 10, UsedPoseidonHashes: 10, UsedPoseidonPaddings: 10, UsedMemAligns: 10, UsedArithmetics: 10, UsedBinaries: 10, UsedSteps: 10}, + usedBytes: 10, + expectedResult: 1000.00, + }, + { + Name: "Using half of the resources", + benefit: 1000000, + counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, + usedBytes: 5, + expectedResult: 2000.00, + }, + { + Name: "Using all the bytes and half of the remain resources", + benefit: 1000000, + counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, + usedBytes: 10, + expectedResult: 1666.67, + }, + { + Name: "Using all the steps and half of the remain resources", + benefit: 1000000, + counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 10}, + usedBytes: 5, + expectedResult: 1818.18, + }, + { + Name: "Using 10% of all the resources", + benefit: 1000000, + counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, + usedBytes: 1, + expectedResult: 10000.00, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.Name, func(t *testing.T) { + tx := TxTracker{} + tx.Benefit = new(big.Int).SetInt64(testCase.benefit) + + tx.BatchResources.Bytes = testCase.usedBytes + tx.updateZKCounters(testCase.counters, rcMax, rcWeigth) + tx.weightMultipliers = calculateWeightMultipliers(rcWeigth, totalWeight) + tx.resourceCostMultiplier = 1000 + tx.updateZKCounters(testCase.counters, rcMax, rcWeigth) + t.Logf("%s=%s", testCase.Name, fmt.Sprintf("%.2f", tx.Efficiency)) + assert.Equal(t, fmt.Sprintf("%.2f", testCase.expectedResult), fmt.Sprintf("%.2f", tx.Efficiency), "Efficiency calculation error. Expected=%s, Actual=%s", fmt.Sprintf("%.2f", testCase.expectedResult), fmt.Sprintf("%.2f", tx.Efficiency)) + }) + } +} diff --git a/sequencer/worker.go b/sequencer/worker.go new file mode 100644 index 0000000000..b138ff55ba --- /dev/null +++ b/sequencer/worker.go @@ -0,0 +1,328 @@ +package sequencer + +import ( + "context" + "fmt" + "math/big" + "runtime" + "sync" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// Worker represents the worker component of the sequencer +type Worker struct { + cfg WorkerCfg + pool map[string]*addrQueue + efficiencyList *efficiencyList + workerMutex sync.Mutex + state stateInterface + batchConstraints batchConstraintsFloat64 + batchResourceWeights batchResourceWeights +} + +// NewWorker creates an init a worker +func NewWorker(cfg WorkerCfg, state stateInterface, constraints batchConstraints, weights batchResourceWeights) *Worker { + w := Worker{ + cfg: cfg, + pool: make(map[string]*addrQueue), + efficiencyList: newEfficiencyList(), + state: state, + batchConstraints: convertBatchConstraintsToFloat64(constraints), + batchResourceWeights: weights, + } + + return &w +} + +// NewTxTracker creates and inits a TxTracker +func (w *Worker) NewTxTracker(tx types.Transaction, counters state.ZKCounters, ip string) (*TxTracker, error) { + return newTxTracker(tx, counters, w.batchConstraints, w.batchResourceWeights, w.cfg.ResourceCostMultiplier, ip) +} + +// AddTxTracker adds a new Tx to the Worker +func (w *Worker) AddTxTracker(ctx context.Context, tx *TxTracker) (dropReason error, isWIP bool) { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + + addr, found := w.pool[tx.FromStr] + + if !found { + // Unlock the worker to let execute other worker functions while creating the new AddrQueue + w.workerMutex.Unlock() + + root, err := w.state.GetLastStateRoot(ctx, nil) + if err != nil { + dropReason = fmt.Errorf("AddTx GetLastStateRoot error: %v", err) + log.Error(dropReason) + return dropReason, false + } + nonce, err := w.state.GetNonceByStateRoot(ctx, tx.From, root) + if err != nil { + dropReason = fmt.Errorf("AddTx GetNonceByStateRoot error: %v", err) + log.Error(dropReason) + return dropReason, false + } + balance, err := w.state.GetBalanceByStateRoot(ctx, tx.From, root) + if err != nil { + dropReason = fmt.Errorf("AddTx GetBalanceByStateRoot error: %v", err) + log.Error(dropReason) + return dropReason, false + } + + addr = newAddrQueue(tx.From, nonce.Uint64(), balance) + + // Lock again the worker + w.workerMutex.Lock() + + w.pool[tx.FromStr] = addr + log.Infof("AddTx new addrQueue created for addr(%s) nonce(%d) balance(%s)", tx.FromStr, nonce.Uint64(), balance.String()) + } + + // Add the txTracker to Addr and get the newReadyTx and prevReadyTx + log.Infof("AddTx new tx(%s) nonce(%d) cost(%s) to addrQueue(%s)", tx.Hash.String(), tx.Nonce, tx.Cost.String(), tx.FromStr) + var newReadyTx, prevReadyTx *TxTracker + newReadyTx, prevReadyTx, dropReason = addr.addTx(tx) + if dropReason != nil { + log.Infof("AddTx tx(%s) dropped from addrQueue(%s)", tx.Hash.String(), tx.FromStr) + return dropReason, false + } + + // Update the EfficiencyList (if needed) + if prevReadyTx != nil { + log.Infof("AddTx prevReadyTx(%s) nonce(%d) cost(%s) deleted from EfficiencyList", prevReadyTx.Hash.String(), prevReadyTx.Nonce, prevReadyTx.Cost.String()) + w.efficiencyList.delete(prevReadyTx) + } + if newReadyTx != nil { + log.Infof("AddTx newReadyTx(%s) nonce(%d) cost(%s) added to EfficiencyList", newReadyTx.Hash.String(), newReadyTx.Nonce, newReadyTx.Cost.String()) + w.efficiencyList.add(newReadyTx) + } + + return nil, true +} + +func (w *Worker) applyAddressUpdate(from common.Address, fromNonce *uint64, fromBalance *big.Int) (*TxTracker, *TxTracker, []*TxTracker) { + addrQueue, found := w.pool[from.String()] + + if found { + newReadyTx, prevReadyTx, txsToDelete := addrQueue.updateCurrentNonceBalance(fromNonce, fromBalance) + + // Update the EfficiencyList (if needed) + if prevReadyTx != nil { + log.Infof("applyAddressUpdate prevReadyTx(%s) nonce(%d) cost(%s) deleted from EfficiencyList", prevReadyTx.Hash.String(), prevReadyTx.Nonce, prevReadyTx.Cost.String()) + w.efficiencyList.delete(prevReadyTx) + } + if newReadyTx != nil { + log.Infof("applyAddressUpdate newReadyTx(%s) nonce(%d) cost(%s) added to EfficiencyList", newReadyTx.Hash.String(), newReadyTx.Nonce, newReadyTx.Cost.String()) + w.efficiencyList.add(newReadyTx) + } + + return newReadyTx, prevReadyTx, txsToDelete + } + + return nil, nil, nil +} + +// UpdateAfterSingleSuccessfulTxExecution updates the touched addresses after execute on Executor a successfully tx +func (w *Worker) UpdateAfterSingleSuccessfulTxExecution(from common.Address, touchedAddresses map[common.Address]*state.InfoReadWrite) []*TxTracker { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + if len(touchedAddresses) == 0 { + log.Errorf("UpdateAfterSingleSuccessfulTxExecution touchedAddresses is nil or empty") + } + txsToDelete := make([]*TxTracker, 0) + touchedFrom, found := touchedAddresses[from] + if found { + fromNonce, fromBalance := touchedFrom.Nonce, touchedFrom.Balance + _, _, txsToDelete = w.applyAddressUpdate(from, fromNonce, fromBalance) + } else { + log.Errorf("UpdateAfterSingleSuccessfulTxExecution from(%s) not found in touchedAddresses", from.String()) + } + + for addr, addressInfo := range touchedAddresses { + if addr != from { + _, _, txsToDeleteTemp := w.applyAddressUpdate(addr, nil, addressInfo.Balance) + txsToDelete = append(txsToDelete, txsToDeleteTemp...) + } + } + return txsToDelete +} + +// MoveTxToNotReady move a tx to not ready after it fails to execute +func (w *Worker) MoveTxToNotReady(txHash common.Hash, from common.Address, actualNonce *uint64, actualBalance *big.Int) []*TxTracker { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + log.Infof("MoveTxToNotReady tx(%s) from(%s) actualNonce(%d) actualBalance(%s)", txHash.String(), from.String(), actualNonce, actualBalance.String()) + + addrQueue, found := w.pool[from.String()] + if found { + // Sanity check. The txHash must be the readyTx + if addrQueue.readyTx == nil || txHash.String() != addrQueue.readyTx.HashStr { + readyHashStr := "" + if addrQueue.readyTx != nil { + readyHashStr = addrQueue.readyTx.HashStr + } + log.Errorf("MoveTxToNotReady txHash(%s) is not the readyTx(%s)", txHash.String(), readyHashStr) + } + } + _, _, txsToDelete := w.applyAddressUpdate(from, actualNonce, actualBalance) + + return txsToDelete +} + +// DeleteTx delete the tx after it fails to execute +func (w *Worker) DeleteTx(txHash common.Hash, addr common.Address) { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + + addrQueue, found := w.pool[addr.String()] + if found { + deletedReadyTx := addrQueue.deleteTx(txHash) + if deletedReadyTx != nil { + log.Infof("DeleteTx tx(%s) deleted from EfficiencyList", deletedReadyTx.Hash.String()) + w.efficiencyList.delete(deletedReadyTx) + } + } else { + log.Errorf("DeleteTx addrQueue(%s) not found", addr.String()) + } +} + +// UpdateTx updates the ZKCounter of a tx and resort the tx in the efficiency list if needed +func (w *Worker) UpdateTx(txHash common.Hash, addr common.Address, counters state.ZKCounters) { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + log.Infof("UpdateTx tx(%s) addr(%s)", txHash.String(), addr.String()) + log.Debugf("UpdateTx counters.CumulativeGasUsed: %d", counters.CumulativeGasUsed) + log.Debugf("UpdateTx counters.UsedKeccakHashes: %d", counters.UsedKeccakHashes) + log.Debugf("UpdateTx counters.UsedPoseidonHashes: %d", counters.UsedPoseidonHashes) + log.Debugf("UpdateTx counters.UsedPoseidonPaddings: %d", counters.UsedPoseidonPaddings) + log.Debugf("UpdateTx counters.UsedMemAligns: %d", counters.UsedMemAligns) + log.Debugf("UpdateTx counters.UsedArithmetics: %d", counters.UsedArithmetics) + log.Debugf("UpdateTx counters.UsedBinaries: %d", counters.UsedBinaries) + log.Debugf("UpdateTx counters.UsedSteps: %d", counters.UsedSteps) + + addrQueue, found := w.pool[addr.String()] + + if found { + newReadyTx, prevReadyTx := addrQueue.UpdateTxZKCounters(txHash, counters, w.batchConstraints, w.batchResourceWeights) + + // Resort the newReadyTx in efficiencyList + if prevReadyTx != nil { + log.Infof("UpdateTx prevReadyTx(%s) nonce(%d) cost(%s) deleted from EfficiencyList", prevReadyTx.Hash.String(), prevReadyTx.Nonce, prevReadyTx.Cost.String()) + w.efficiencyList.delete(prevReadyTx) + } + if newReadyTx != nil { + log.Infof("UpdateTx newReadyTx(%s) nonce(%d) cost(%s) added to EfficiencyList", newReadyTx.Hash.String(), newReadyTx.Nonce, newReadyTx.Cost.String()) + w.efficiencyList.add(newReadyTx) + } + } else { + log.Errorf("UpdateTx addrQueue(%s) not found", addr.String()) + } +} + +// GetBestFittingTx gets the most efficient tx that fits in the available batch resources +func (w *Worker) GetBestFittingTx(resources state.BatchResources) *TxTracker { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + + var ( + tx *TxTracker + foundMutex sync.RWMutex + ) + + nGoRoutines := runtime.NumCPU() + foundAt := -1 + + wg := sync.WaitGroup{} + wg.Add(nGoRoutines) + + // Each go routine looks for a fitting tx + for i := 0; i < nGoRoutines; i++ { + go func(n int, bresources state.BatchResources) { + defer wg.Done() + for i := n; i < w.efficiencyList.len(); i += nGoRoutines { + foundMutex.RLock() + if foundAt != -1 && i > foundAt { + foundMutex.RUnlock() + return + } + foundMutex.RUnlock() + + txCandidate := w.efficiencyList.getByIndex(i) + err := bresources.Sub(txCandidate.BatchResources) + if err != nil { + // We don't add this Tx + continue + } + + foundMutex.Lock() + if foundAt == -1 || foundAt > i { + foundAt = i + tx = txCandidate + log.Infof("GetBestFittingTx found tx(%s) at index(%d) with efficiency(%f)", tx.Hash.String(), i, tx.Efficiency) + } + foundMutex.Unlock() + + return + } + }(i, resources) + } + wg.Wait() + + return tx +} + +// ExpireTransactions deletes old txs +func (w *Worker) ExpireTransactions(maxTime time.Duration) []*TxTracker { + w.workerMutex.Lock() + defer w.workerMutex.Unlock() + + var txs []*TxTracker + + log.Info("ExpireTransactions start. addrQueue len: ", len(w.pool)) + for _, addrQueue := range w.pool { + subTxs, prevReadyTx := addrQueue.ExpireTransactions(maxTime) + txs = append(txs, subTxs...) + + if prevReadyTx != nil { + w.efficiencyList.delete(prevReadyTx) + } + + if addrQueue.IsEmpty() { + delete(w.pool, addrQueue.fromStr) + } + } + log.Info("ExpireTransactions end. addrQueue len: ", len(w.pool), " deleteCount: ", len(txs)) + + return txs +} + +// GetEfficiencyList returns the efficiency list +func (w *Worker) GetEfficiencyList() *efficiencyList { + return w.efficiencyList +} + +// HandleL2Reorg handles the L2 reorg signal +func (w *Worker) HandleL2Reorg(txHashes []common.Hash) { + log.Fatal("L2 Reorg detected. Restarting to sync with the new L2 state...") +} + +// convertBatchConstraintsToFloat64 converts the batch constraints to float64 +func convertBatchConstraintsToFloat64(constraints batchConstraints) batchConstraintsFloat64 { + return batchConstraintsFloat64{ + maxTxsPerBatch: float64(constraints.MaxTxsPerBatch), + maxBatchBytesSize: float64(constraints.MaxBatchBytesSize), + maxCumulativeGasUsed: float64(constraints.MaxCumulativeGasUsed), + maxKeccakHashes: float64(constraints.MaxKeccakHashes), + maxPoseidonHashes: float64(constraints.MaxPoseidonHashes), + maxPoseidonPaddings: float64(constraints.MaxPoseidonPaddings), + maxMemAligns: float64(constraints.MaxMemAligns), + maxArithmetics: float64(constraints.MaxArithmetics), + maxBinaries: float64(constraints.MaxBinaries), + maxSteps: float64(constraints.MaxSteps), + } +} diff --git a/sequencer/worker_test.go b/sequencer/worker_test.go new file mode 100644 index 0000000000..0c34d85874 --- /dev/null +++ b/sequencer/worker_test.go @@ -0,0 +1,312 @@ +package sequencer + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +var ( + workerCfg = WorkerCfg{ + ResourceCostMultiplier: 1000, + } +) + +type workerAddTxTestCase struct { + name string + from common.Address + txHash common.Hash + nonce uint64 + // isClaim bool + benefit int64 + cost *big.Int + counters state.ZKCounters + usedBytes uint64 + expectedEfficiencyList []common.Hash +} + +type workerAddrQueueInfo struct { + from common.Address + nonce *big.Int + balance *big.Int +} + +func processWorkerAddTxTestCases(t *testing.T, worker *Worker, testCases []workerAddTxTestCase) { + totalWeight := float64(worker.batchResourceWeights.WeightArithmetics + + worker.batchResourceWeights.WeightBatchBytesSize + worker.batchResourceWeights.WeightBinaries + + worker.batchResourceWeights.WeightCumulativeGasUsed + worker.batchResourceWeights.WeightKeccakHashes + + worker.batchResourceWeights.WeightMemAligns + worker.batchResourceWeights.WeightPoseidonHashes + + worker.batchResourceWeights.WeightPoseidonPaddings + worker.batchResourceWeights.WeightSteps) + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + tx := TxTracker{} + + tx.weightMultipliers = calculateWeightMultipliers(worker.batchResourceWeights, totalWeight) + tx.constraints = worker.batchConstraints + tx.resourceCostMultiplier = worker.cfg.ResourceCostMultiplier + tx.Hash = testCase.txHash + tx.HashStr = testCase.txHash.String() + tx.From = testCase.from + tx.FromStr = testCase.from.String() + tx.Nonce = testCase.nonce + tx.Benefit = new(big.Int).SetInt64(testCase.benefit) + tx.Cost = testCase.cost + tx.BatchResources.Bytes = testCase.usedBytes + tx.updateZKCounters(testCase.counters, worker.batchConstraints, worker.batchResourceWeights) + t.Logf("%s=%s", testCase.name, fmt.Sprintf("%.2f", tx.Efficiency)) + + err, _ := worker.AddTxTracker(ctx, &tx) + if err != nil { + return + } + + el := worker.efficiencyList + if el.len() != len(testCase.expectedEfficiencyList) { + t.Fatalf("Error efficiencylist.len(%d) != expectedEfficiencyList.len(%d)", el.len(), len(testCase.expectedEfficiencyList)) + } + for i := 0; i < el.len(); i++ { + if el.getByIndex(i).HashStr != string(testCase.expectedEfficiencyList[i].String()) { + t.Fatalf("Error efficiencylist(%d). Expected=%s, Actual=%s", i, testCase.expectedEfficiencyList[i].String(), el.getByIndex(i).HashStr) + } + } + }) + } +} + +func TestWorkerAddTx(t *testing.T) { + var nilErr error + + // Init ZKEVM resourceCostWeight values + rcWeigth := batchResourceWeights{} + rcWeigth.WeightCumulativeGasUsed = 1 + rcWeigth.WeightArithmetics = 1 + rcWeigth.WeightBinaries = 1 + rcWeigth.WeightKeccakHashes = 1 + rcWeigth.WeightMemAligns = 1 + rcWeigth.WeightPoseidonHashes = 1 + rcWeigth.WeightPoseidonPaddings = 1 + rcWeigth.WeightSteps = 1 + rcWeigth.WeightBatchBytesSize = 2 + + // Init ZKEVM resourceCostMax values + rcMax := batchConstraints{} + rcMax.MaxCumulativeGasUsed = 10 + rcMax.MaxArithmetics = 10 + rcMax.MaxBinaries = 10 + rcMax.MaxKeccakHashes = 10 + rcMax.MaxMemAligns = 10 + rcMax.MaxPoseidonHashes = 10 + rcMax.MaxPoseidonPaddings = 10 + rcMax.MaxSteps = 10 + rcMax.MaxBatchBytesSize = 10 + + stateMock := NewStateMock(t) + worker := initWorker(stateMock, rcMax, rcWeigth) + + ctx := context.Background() + + stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr) + + addrQueueInfo := []workerAddrQueueInfo{ + {from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + } + + for _, aq := range addrQueueInfo { + stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr) + stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr) + } + + addTxsTC := []workerAddTxTestCase{ + { + name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1, + benefit: 1000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, + usedBytes: 1, + expectedEfficiencyList: []common.Hash{ + {1}, + }, + }, + { + name: "Adding from:0x02, tx:0x02/ef:20", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, + benefit: 2000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, + usedBytes: 1, + expectedEfficiencyList: []common.Hash{ + {2}, {1}, + }, + }, + { + name: "Readding from:0x02, tx:0x02/ef:4", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, + benefit: 2000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, + usedBytes: 5, + expectedEfficiencyList: []common.Hash{ + {1}, {2}, + }, + }, + { + name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1, + benefit: 5000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2}, + usedBytes: 2, + expectedEfficiencyList: []common.Hash{ + {3}, {1}, {2}, + }, + }, + } + + processWorkerAddTxTestCases(t, worker, addTxsTC) + + // Change counters fpr tx:0x03/ef:9.61 + counters := state.ZKCounters{CumulativeGasUsed: 6, UsedKeccakHashes: 6, UsedPoseidonHashes: 6, UsedPoseidonPaddings: 6, UsedMemAligns: 6, UsedArithmetics: 6, UsedBinaries: 6, UsedSteps: 6} + worker.UpdateTx(common.Hash{3}, common.Address{3}, counters) + + addTxsTC = []workerAddTxTestCase{ + { + name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1, + benefit: 10000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, + usedBytes: 1, + expectedEfficiencyList: []common.Hash{ + {4}, {1}, {3}, {2}, + }, + }, + } + + processWorkerAddTxTestCases(t, worker, addTxsTC) +} + +func TestWorkerGetBestTx(t *testing.T) { + var nilErr error + + // Init ZKEVM resourceCostWeight values + rcWeight := batchResourceWeights{} + rcWeight.WeightCumulativeGasUsed = 1 + rcWeight.WeightArithmetics = 1 + rcWeight.WeightBinaries = 1 + rcWeight.WeightKeccakHashes = 1 + rcWeight.WeightMemAligns = 1 + rcWeight.WeightPoseidonHashes = 1 + rcWeight.WeightPoseidonPaddings = 1 + rcWeight.WeightSteps = 1 + rcWeight.WeightBatchBytesSize = 2 + + // Init ZKEVM resourceCostMax values + rcMax := batchConstraints{} + rcMax.MaxCumulativeGasUsed = 10 + rcMax.MaxArithmetics = 10 + rcMax.MaxBinaries = 10 + rcMax.MaxKeccakHashes = 10 + rcMax.MaxMemAligns = 10 + rcMax.MaxPoseidonHashes = 10 + rcMax.MaxPoseidonPaddings = 10 + rcMax.MaxSteps = 10 + rcMax.MaxBatchBytesSize = 10 + + rc := state.BatchResources{ + ZKCounters: state.ZKCounters{CumulativeGasUsed: 10, UsedKeccakHashes: 10, UsedPoseidonHashes: 10, UsedPoseidonPaddings: 10, UsedMemAligns: 10, UsedArithmetics: 10, UsedBinaries: 10, UsedSteps: 10}, + Bytes: 10, + } + + stateMock := NewStateMock(t) + worker := initWorker(stateMock, rcMax, rcWeight) + + ctx := context.Background() + + stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr) + + addrQueueInfo := []workerAddrQueueInfo{ + {from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + {from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, + } + + for _, aq := range addrQueueInfo { + stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr) + stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr) + } + + addTxsTC := []workerAddTxTestCase{ + { + name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1, + benefit: 1000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, + usedBytes: 1, + expectedEfficiencyList: []common.Hash{ + {1}, + }, + }, + { + name: "Adding from:0x02, tx:0x02/ef:12", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, + benefit: 6000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, + usedBytes: 5, + expectedEfficiencyList: []common.Hash{ + {2}, {1}, + }, + }, + { + name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1, + benefit: 5000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2}, + usedBytes: 2, + expectedEfficiencyList: []common.Hash{ + {3}, {2}, {1}, + }, + }, + { + name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1, + benefit: 40000, cost: new(big.Int).SetInt64(5), + counters: state.ZKCounters{CumulativeGasUsed: 4, UsedKeccakHashes: 4, UsedPoseidonHashes: 4, UsedPoseidonPaddings: 4, UsedMemAligns: 4, UsedArithmetics: 4, UsedBinaries: 4, UsedSteps: 4}, + usedBytes: 4, + expectedEfficiencyList: []common.Hash{ + {4}, {3}, {2}, {1}, + }, + }, + } + + processWorkerAddTxTestCases(t, worker, addTxsTC) + + expectedGetBestTx := []common.Hash{{4}, {3}, {1}} + ct := 0 + + for { + tx := worker.GetBestFittingTx(rc) + if tx != nil { + if ct >= len(expectedGetBestTx) { + t.Fatalf("Error getting more best tx than expected. Expected=%d, Actual=%d", len(expectedGetBestTx), ct+1) + } + if tx.HashStr != string(expectedGetBestTx[ct].String()) { + t.Fatalf("Error GetBestFittingTx(%d). Expected=%s, Actual=%s", ct, expectedGetBestTx[ct].String(), tx.HashStr) + } + err := rc.Sub(tx.BatchResources) + assert.NoError(t, err) + + touch := make(map[common.Address]*state.InfoReadWrite) + var newNonce uint64 = tx.Nonce + 1 + touch[tx.From] = &state.InfoReadWrite{Address: tx.From, Nonce: &newNonce, Balance: new(big.Int).SetInt64(10)} + worker.UpdateAfterSingleSuccessfulTxExecution(tx.From, touch) + ct++ + } else { + if ct < len(expectedGetBestTx) { + t.Fatalf("Error expecting more best tx. Expected=%d, Actual=%d", len(expectedGetBestTx), ct) + } + break + } + } +} + +func initWorker(stateMock *StateMock, rcMax batchConstraints, rcWeigth batchResourceWeights) *Worker { + worker := NewWorker(workerCfg, stateMock, rcMax, rcWeigth) + return worker +} diff --git a/sequencesender/config.go b/sequencesender/config.go new file mode 100644 index 0000000000..84e2b3535c --- /dev/null +++ b/sequencesender/config.go @@ -0,0 +1,25 @@ +package sequencesender + +import ( + "github.com/0xPolygonHermez/zkevm-node/config/types" +) + +// Config represents the configuration of a sequence sender +type Config struct { + // WaitPeriodSendSequence is the time the sequencer waits until + // trying to send a sequence to L1 + WaitPeriodSendSequence types.Duration `mapstructure:"WaitPeriodSendSequence"` + // LastBatchVirtualizationTimeMaxWaitPeriod is time since sequences should be sent + LastBatchVirtualizationTimeMaxWaitPeriod types.Duration `mapstructure:"LastBatchVirtualizationTimeMaxWaitPeriod"` + // MaxTxSizeForL1 is the maximum size a single transaction can have. This field has + // non-trivial consequences: larger transactions than 128KB are significantly harder and + // more expensive to propagate; larger transactions also take more resources + // to validate whether they fit into the pool or not. + MaxTxSizeForL1 uint64 `mapstructure:"MaxTxSizeForL1"` + // SenderAddress defines which private key the eth tx manager needs to use + // to sign the L1 txs + SenderAddress string `mapstructure:"SenderAddress"` + // PrivateKeys defines all the key store files that are going + // to be read in order to provide the private keys to sign the L1 txs + PrivateKeys []types.KeystoreFileConfig `mapstructure:"PrivateKeys"` +} diff --git a/sequencesender/interfaces.go b/sequencesender/interfaces.go new file mode 100644 index 0000000000..d203e13c29 --- /dev/null +++ b/sequencesender/interfaces.go @@ -0,0 +1,40 @@ +package sequencesender + +import ( + "context" + "math/big" + "time" + + ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +// Consumer interfaces required by the package. + +// etherman contains the methods required to interact with ethereum. +type etherman interface { + BuildSequenceBatchesTxData(sender common.Address, sequences []ethmanTypes.Sequence) (to *common.Address, data []byte, err error) + EstimateGasSequenceBatches(sender common.Address, sequences []ethmanTypes.Sequence) (*types.Transaction, error) + GetLastBatchTimestamp() (uint64, error) + GetLatestBlockTimestamp(ctx context.Context) (uint64, error) + GetLatestBatchNumber() (uint64, error) +} + +// stateInterface gathers the methods required to interact with the state. +type stateInterface interface { + GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) + IsBatchClosed(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (bool, error) + GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) + GetForcedBatch(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (*state.ForcedBatch, error) + GetTimeForLatestBatchVirtualization(ctx context.Context, dbTx pgx.Tx) (time.Time, error) + GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) +} + +type ethTxManager interface { + Add(ctx context.Context, owner, id string, from common.Address, to *common.Address, value *big.Int, data []byte, dbTx pgx.Tx) error + ProcessPendingMonitoredTxs(ctx context.Context, owner string, failedResultHandler ethtxmanager.ResultHandler, dbTx pgx.Tx) +} diff --git a/sequencesender/sequencesender.go b/sequencesender/sequencesender.go new file mode 100644 index 0000000000..b041b20ca4 --- /dev/null +++ b/sequencesender/sequencesender.go @@ -0,0 +1,328 @@ +package sequencesender + +import ( + "context" + "errors" + "fmt" + "time" + + ethman "github.com/0xPolygonHermez/zkevm-node/etherman" + "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/ethtxmanager" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +const ( + ethTxManagerOwner = "sequencer" + monitoredIDFormat = "sequence-from-%v-to-%v" +) + +var ( + // ErrOversizedData is returned if the input data of a transaction is greater + // than some meaningful limit a user might use. This is not a consensus error + // making the transaction invalid, rather a DOS protection. + ErrOversizedData = errors.New("oversized data") +) + +// SequenceSender represents a sequence sender +type SequenceSender struct { + cfg Config + state stateInterface + ethTxManager ethTxManager + etherman etherman + eventLog *event.EventLog +} + +// New inits sequence sender +func New(cfg Config, state stateInterface, etherman etherman, manager ethTxManager, eventLog *event.EventLog) (*SequenceSender, error) { + return &SequenceSender{ + cfg: cfg, + state: state, + etherman: etherman, + ethTxManager: manager, + eventLog: eventLog, + }, nil +} + +// Start starts the sequence sender +func (s *SequenceSender) Start(ctx context.Context) { + ticker := time.NewTicker(s.cfg.WaitPeriodSendSequence.Duration) + for { + s.tryToSendSequence(ctx, ticker) + } +} + +func (s *SequenceSender) tryToSendSequence(ctx context.Context, ticker *time.Ticker) { + retry := false + // process monitored sequences before starting a next cycle + s.ethTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) { + if result.Status == ethtxmanager.MonitoredTxStatusFailed { + retry = true + resultLog := log.WithFields("owner", ethTxManagerOwner, "id", result.ID) + resultLog.Error("failed to send sequence, TODO: review this fatal and define what to do in this case") + } + }, nil) + + if retry { + return + } + + // Check if synchronizer is up to date + if !s.isSynced(ctx) { + log.Info("wait for synchronizer to sync last batch") + waitTick(ctx, ticker) + return + } + + // Check if should send sequence to L1 + log.Infof("getting sequences to send") + sequences, err := s.getSequencesToSend(ctx) + if err != nil || len(sequences) == 0 { + if err != nil { + log.Errorf("error getting sequences: %v", err) + } else { + log.Info("waiting for sequences to be worth sending to L1") + } + waitTick(ctx, ticker) + return + } + + lastVirtualBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) + if err != nil { + log.Errorf("failed to get last virtual batch num, err: %v", err) + return + } + + // Send sequences to L1 + sequenceCount := len(sequences) + log.Infof( + "sending sequences to L1. From batch %d to batch %d", + lastVirtualBatchNum+1, lastVirtualBatchNum+uint64(sequenceCount), + ) + metrics.SequencesSentToL1(float64(sequenceCount)) + + // add sequence to be monitored + sender := common.HexToAddress(s.cfg.SenderAddress) + to, data, err := s.etherman.BuildSequenceBatchesTxData(sender, sequences) + if err != nil { + log.Error("error estimating new sequenceBatches to add to eth tx manager: ", err) + return + } + firstSequence := sequences[0] + lastSequence := sequences[len(sequences)-1] + monitoredTxID := fmt.Sprintf(monitoredIDFormat, firstSequence.BatchNumber, lastSequence.BatchNumber) + err = s.ethTxManager.Add(ctx, ethTxManagerOwner, monitoredTxID, sender, to, nil, data, nil) + if err != nil { + log.Error("error to add sequences tx to eth tx manager: ", err) + return + } +} + +// getSequencesToSend generates an array of sequences to be send to L1. +// If the array is empty, it doesn't necessarily mean that there are no sequences to be sent, +// it could be that it's not worth it to do so yet. +func (s *SequenceSender) getSequencesToSend(ctx context.Context) ([]types.Sequence, error) { + lastVirtualBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) + if err != nil { + return nil, fmt.Errorf("failed to get last virtual batch num, err: %w", err) + } + + currentBatchNumToSequence := lastVirtualBatchNum + 1 + sequences := []types.Sequence{} + // var estimatedGas uint64 + + var tx *ethTypes.Transaction + + // Add sequences until too big for a single L1 tx or last batch is reached + for { + // Check if batch is closed + isClosed, err := s.state.IsBatchClosed(ctx, currentBatchNumToSequence, nil) + if err != nil { + return nil, err + } + if !isClosed { + // Reached current (WIP) batch + break + } + // Add new sequence + batch, err := s.state.GetBatchByNumber(ctx, currentBatchNumToSequence, nil) + if err != nil { + return nil, err + } + + seq := types.Sequence{ + GlobalExitRoot: batch.GlobalExitRoot, + Timestamp: batch.Timestamp.Unix(), + BatchL2Data: batch.BatchL2Data, + BatchNumber: batch.BatchNumber, + } + + if batch.ForcedBatchNum != nil { + forcedBatch, err := s.state.GetForcedBatch(ctx, *batch.ForcedBatchNum, nil) + if err != nil { + return nil, err + } + seq.ForcedBatchTimestamp = forcedBatch.ForcedAt.Unix() + } + + sequences = append(sequences, seq) + // Check if can be send + sender := common.HexToAddress(s.cfg.SenderAddress) + tx, err = s.etherman.EstimateGasSequenceBatches(sender, sequences) + if err == nil && tx.Size() > s.cfg.MaxTxSizeForL1 { + metrics.SequencesOvesizedDataError() + log.Infof("oversized Data on TX oldHash %s (txSize %d > 128KB)", tx.Hash(), tx.Size()) + err = ErrOversizedData + } + if err != nil { + log.Infof("Handling estimage gas send sequence error: %v", err) + sequences, err = s.handleEstimateGasSendSequenceErr(ctx, sequences, currentBatchNumToSequence, err) + if sequences != nil { + // Handling the error gracefully, re-processing the sequence as a sanity check + _, err = s.etherman.EstimateGasSequenceBatches(sender, sequences) + return sequences, err + } + return sequences, err + } + // estimatedGas = tx.Gas() + + // Increase batch num for next iteration + currentBatchNumToSequence++ + } + + // Reached latest batch. Decide if it's worth to send the sequence, or wait for new batches + if len(sequences) == 0 { + log.Info("no batches to be sequenced") + return nil, nil + } + + lastBatchVirtualizationTime, err := s.state.GetTimeForLatestBatchVirtualization(ctx, nil) + if err != nil && !errors.Is(err, state.ErrNotFound) { + log.Warnf("failed to get last l1 interaction time, err: %v. Sending sequences as a conservative approach", err) + return sequences, nil + } + if lastBatchVirtualizationTime.Before(time.Now().Add(-s.cfg.LastBatchVirtualizationTimeMaxWaitPeriod.Duration)) { + // TODO: implement check profitability + // if s.checker.IsSendSequencesProfitable(new(big.Int).SetUint64(estimatedGas), sequences) { + log.Info("sequence should be sent to L1, because too long since didn't send anything to L1") + return sequences, nil + //} + } + + log.Info("not enough time has passed since last batch was virtualized, and the sequence could be bigger") + return nil, nil +} + +// handleEstimateGasSendSequenceErr handles an error on the estimate gas. It will return: +// nil, error: impossible to handle gracefully +// sequence, nil: handled gracefully. Potentially manipulating the sequences +// nil, nil: a situation that requires waiting +func (s *SequenceSender) handleEstimateGasSendSequenceErr( + ctx context.Context, + sequences []types.Sequence, + currentBatchNumToSequence uint64, + err error, +) ([]types.Sequence, error) { + // Insufficient allowance + if errors.Is(err, ethman.ErrInsufficientAllowance) { + return nil, err + } + if isDataForEthTxTooBig(err) { + // Remove the latest item and send the sequences + log.Infof( + "Done building sequences, selected batches to %d. Batch %d caused the L1 tx to be too big", + currentBatchNumToSequence-1, currentBatchNumToSequence, + ) + sequences = sequences[:len(sequences)-1] + return sequences, nil + } + + // while estimating gas a new block is not created and the POE SC may return + // an error regarding timestamp verification, this must be handled + if errors.Is(err, ethman.ErrTimestampMustBeInsideRange) { + // query the sc about the value of its lastTimestamp variable + lastTimestamp, err := s.etherman.GetLastBatchTimestamp() + if err != nil { + return nil, err + } + // check POE SC lastTimestamp against sequences' one + for _, seq := range sequences { + if seq.Timestamp < int64(lastTimestamp) { + // TODO: gracefully handle this situation by creating an L2 reorg + log.Fatalf("sequence timestamp %d is < POE SC lastTimestamp %d", seq.Timestamp, lastTimestamp) + } + lastTimestamp = uint64(seq.Timestamp) + } + blockTimestamp, err := s.etherman.GetLatestBlockTimestamp(ctx) + if err != nil { + log.Error("error getting block timestamp: ", err) + } + log.Debugf("block.timestamp: %d is smaller than seq.Timestamp: %d. A new block must be mined in L1 before the gas can be estimated.", blockTimestamp, sequences[0].Timestamp) + return nil, nil + } + + // Unknown error + if len(sequences) == 1 { + // TODO: gracefully handle this situation by creating an L2 reorg + log.Errorf( + "Error when estimating gas for BatchNum %d (alone in the sequences): %v", + currentBatchNumToSequence, err, + ) + } + // Remove the latest item and send the sequences + log.Infof( + "Done building sequences, selected batches to %d. Batch %d excluded due to unknown error: %v", + currentBatchNumToSequence, currentBatchNumToSequence+1, err, + ) + sequences = sequences[:len(sequences)-1] + + return sequences, nil +} + +func isDataForEthTxTooBig(err error) bool { + return errors.Is(err, ethman.ErrGasRequiredExceedsAllowance) || + errors.Is(err, ErrOversizedData) || + errors.Is(err, ethman.ErrContentLengthTooLarge) +} + +func waitTick(ctx context.Context, ticker *time.Ticker) { + select { + case <-ticker.C: + // nothing + case <-ctx.Done(): + return + } +} + +func (s *SequenceSender) isSynced(ctx context.Context) bool { + lastSyncedBatchNum, err := s.state.GetLastVirtualBatchNum(ctx, nil) + if err != nil && err != state.ErrNotFound { + log.Errorf("failed to get last isSynced batch, err: %v", err) + return false + } + lastBatchNum, err := s.state.GetLastBatchNumber(ctx, nil) + if err != nil && err != state.ErrNotFound { + log.Errorf("failed to get last batch num, err: %v", err) + return false + } + if lastBatchNum > lastSyncedBatchNum { + return true + } + lastEthBatchNum, err := s.etherman.GetLatestBatchNumber() + if err != nil { + log.Errorf("failed to get last eth batch, err: %v", err) + return false + } + if lastSyncedBatchNum < lastEthBatchNum { + log.Infof("waiting for the state to be isSynced, lastSyncedBatchNum: %d, lastEthBatchNum: %d", lastSyncedBatchNum, lastEthBatchNum) + return false + } + + return true +} diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000000..6ddc88abf2 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1 @@ +sonar.projectKey=zkevm-node diff --git a/state/batch.go b/state/batch.go index b988fa73bc..36622be633 100644 --- a/state/batch.go +++ b/state/batch.go @@ -1,10 +1,24 @@ package state import ( + "context" + "errors" + "fmt" "time" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/jackc/pgx/v4" +) + +const ( + cTrue = 1 + cFalse = 0 ) // Batch struct @@ -14,9 +28,11 @@ type Batch struct { BatchL2Data []byte StateRoot common.Hash LocalExitRoot common.Hash + AccInputHash common.Hash Timestamp time.Time Transactions []types.Transaction GlobalExitRoot common.Hash + ForcedBatchNum *uint64 } // ProcessingContext is the necessary data that a batch needs to provide to the runtime, @@ -26,13 +42,37 @@ type ProcessingContext struct { Coinbase common.Address Timestamp time.Time GlobalExitRoot common.Hash + ForcedBatchNum *uint64 } -// ProcessingReceipt indicates the outcome (StateRoot, LocalExitRoot) of processing a batch +// ClosingReason represents the reason why a batch is closed. +type ClosingReason string + +const ( + // BatchFullClosingReason is the closing reason used when a batch is closed when it is full + BatchFullClosingReason ClosingReason = "Batch is full" + // ForcedBatchClosingReason is the closing reason used when a batch is closed because it is forced + ForcedBatchClosingReason ClosingReason = "Forced Batch" + // BatchAlmostFullClosingReason is the closing reason used when the batch it is almost full + BatchAlmostFullClosingReason ClosingReason = "Batch is almost full" + // ForcedBatchDeadlineClosingReason is the closing reason used when forced batch deadline is reached + ForcedBatchDeadlineClosingReason ClosingReason = "Forced Batch deadline" + // TimeoutResolutionDeadlineClosingReason is the closing reason used when timeout resolution deadline is reached + TimeoutResolutionDeadlineClosingReason ClosingReason = "timeout resolution deadline" + // GlobalExitRootDeadlineClosingReason is the closing reason used when Global Exit Root deadline is reached + GlobalExitRootDeadlineClosingReason ClosingReason = "Global Exit Root deadline" +) + +// ProcessingReceipt indicates the outcome (StateRoot, AccInputHash) of processing a batch type ProcessingReceipt struct { BatchNumber uint64 StateRoot common.Hash LocalExitRoot common.Hash + AccInputHash common.Hash + // Txs []types.Transaction + BatchL2Data []byte + ClosingReason ClosingReason + BatchResources BatchResources } // VerifiedBatch represents a VerifiedBatch @@ -41,12 +81,404 @@ type VerifiedBatch struct { BatchNumber uint64 Aggregator common.Address TxHash common.Hash + StateRoot common.Hash + IsTrusted bool } // VirtualBatch represents a VirtualBatch type VirtualBatch struct { - BatchNumber uint64 - TxHash common.Hash - Coinbase common.Address - BlockNumber uint64 + BatchNumber uint64 + TxHash common.Hash + Coinbase common.Address + SequencerAddr common.Address + BlockNumber uint64 +} + +// Sequence represents the sequence interval +type Sequence struct { + FromBatchNumber uint64 + ToBatchNumber uint64 +} + +// OpenBatch adds a new batch into the state, with the necessary data to start processing transactions within it. +// It's meant to be used by sequencers, since they don't necessarily know what transactions are going to be added +// in this batch yet. In other words it's the creation of a WIP batch. +// Note that this will add a batch with batch number N + 1, where N it's the greatest batch number on the state. +func (s *State) OpenBatch(ctx context.Context, processingContext ProcessingContext, dbTx pgx.Tx) error { + if dbTx == nil { + return ErrDBTxNil + } + // Check if the batch that is being opened has batch num + 1 compared to the latest batch + lastBatchNum, err := s.PostgresStorage.GetLastBatchNumber(ctx, dbTx) + if err != nil { + return err + } + if lastBatchNum+1 != processingContext.BatchNumber { + return fmt.Errorf("%w number %d, should be %d", ErrUnexpectedBatch, processingContext.BatchNumber, lastBatchNum+1) + } + // Check if last batch is closed + isLastBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, lastBatchNum, dbTx) + if err != nil { + return err + } + if !isLastBatchClosed { + return ErrLastBatchShouldBeClosed + } + // Check that timestamp is equal or greater compared to previous batch + prevTimestamp, err := s.GetLastBatchTime(ctx, dbTx) + if err != nil { + return err + } + if prevTimestamp.Unix() > processingContext.Timestamp.Unix() { + return ErrTimestampGE + } + return s.PostgresStorage.openBatch(ctx, processingContext, dbTx) +} + +// ProcessSequencerBatch is used by the sequencers to process transactions into an open batch +func (s *State) ProcessSequencerBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*ProcessBatchResponse, error) { + log.Debugf("*******************************************") + log.Debugf("ProcessSequencerBatch start") + + processBatchResponse, err := s.processBatch(ctx, batchNumber, batchL2Data, caller, dbTx) + if err != nil { + return nil, err + } + + txs := []types.Transaction{} + + if processBatchResponse.Responses != nil && len(processBatchResponse.Responses) > 0 { + txs, _, err = DecodeTxs(batchL2Data) + if err != nil && !errors.Is(err, ErrInvalidData) { + return nil, err + } + } + + result, err := s.convertToProcessBatchResponse(txs, processBatchResponse) + if err != nil { + return nil, err + } + log.Debugf("ProcessSequencerBatch end") + log.Debugf("*******************************************") + return result, nil +} + +// ProcessBatch processes a batch +func (s *State) ProcessBatch(ctx context.Context, request ProcessRequest, updateMerkleTree bool) (*ProcessBatchResponse, error) { + log.Debugf("*******************************************") + log.Debugf("ProcessBatch start") + + updateMT := uint32(cFalse) + if updateMerkleTree { + updateMT = cTrue + } + + forkID := GetForkIDByBatchNumber(s.cfg.ForkIDIntervals, request.BatchNumber) + + // Create Batch + var processBatchRequest = &pb.ProcessBatchRequest{ + OldBatchNum: request.BatchNumber - 1, + Coinbase: request.Coinbase.String(), + BatchL2Data: request.Transactions, + OldStateRoot: request.OldStateRoot.Bytes(), + GlobalExitRoot: request.GlobalExitRoot.Bytes(), + OldAccInputHash: request.OldAccInputHash.Bytes(), + EthTimestamp: uint64(request.Timestamp.Unix()), + UpdateMerkleTree: updateMT, + ChainId: s.cfg.ChainID, + ForkId: forkID, + } + res, err := s.sendBatchRequestToExecutor(ctx, processBatchRequest, request.Caller) + if err != nil { + return nil, err + } + + txs, _, err := DecodeTxs(request.Transactions) + if err != nil && !errors.Is(err, ErrInvalidData) { + return nil, err + } + + var result *ProcessBatchResponse + result, err = s.convertToProcessBatchResponse(txs, res) + if err != nil { + return nil, err + } + + log.Debugf("ProcessBatch end") + log.Debugf("*******************************************") + + return result, nil +} + +// ExecuteBatch is used by the synchronizer to reprocess batches to compare generated state root vs stored one +// It is also used by the sequencer in order to calculate used zkCounter of a WIPBatch +func (s *State) ExecuteBatch(ctx context.Context, batch Batch, updateMerkleTree bool, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { + if dbTx == nil { + return nil, ErrDBTxNil + } + + // Get previous batch to get state root and local exit root + previousBatch, err := s.PostgresStorage.GetBatchByNumber(ctx, batch.BatchNumber-1, dbTx) + if err != nil { + return nil, err + } + + forkId := s.GetForkIDByBatchNumber(batch.BatchNumber) + + updateMT := uint32(cFalse) + if updateMerkleTree { + updateMT = cTrue + } + + // Create Batch + processBatchRequest := &pb.ProcessBatchRequest{ + OldBatchNum: batch.BatchNumber - 1, + Coinbase: batch.Coinbase.String(), + BatchL2Data: batch.BatchL2Data, + OldStateRoot: previousBatch.StateRoot.Bytes(), + GlobalExitRoot: batch.GlobalExitRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + EthTimestamp: uint64(batch.Timestamp.Unix()), + // Changed for new sequencer strategy + UpdateMerkleTree: updateMT, + ChainId: s.cfg.ChainID, + ForkId: forkId, + } + + // Send Batch to the Executor + log.Debugf("ExecuteBatch[processBatchRequest.OldBatchNum]: %v", processBatchRequest.OldBatchNum) + log.Debugf("ExecuteBatch[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) + log.Debugf("ExecuteBatch[processBatchRequest.From]: %v", processBatchRequest.From) + log.Debugf("ExecuteBatch[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) + log.Debugf("ExecuteBatch[processBatchRequest.GlobalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) + log.Debugf("ExecuteBatch[processBatchRequest.OldAccInputHash]: %v", hex.EncodeToHex(processBatchRequest.OldAccInputHash)) + log.Debugf("ExecuteBatch[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) + log.Debugf("ExecuteBatch[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) + log.Debugf("ExecuteBatch[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) + log.Debugf("ExecuteBatch[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) + log.Debugf("ExecuteBatch[processBatchRequest.ForkId]: %v", processBatchRequest.ForkId) + + processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) + if err != nil { + log.Error("error executing batch: ", err) + return nil, err + } else if processBatchResponse != nil && processBatchResponse.Error != executor.EXECUTOR_ERROR_NO_ERROR { + err = executor.ExecutorErr(processBatchResponse.Error) + s.eventLog.LogExecutorError(ctx, processBatchResponse.Error, processBatchRequest) + } + + return processBatchResponse, err +} + +/* +func uint32ToBool(value uint32) bool { + return value != 0 +} +*/ + +func (s *State) processBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { + if dbTx == nil { + return nil, ErrDBTxNil + } + if s.executorClient == nil { + return nil, ErrExecutorNil + } + + lastBatches, err := s.PostgresStorage.GetLastNBatches(ctx, two, dbTx) + if err != nil { + return nil, err + } + + // Get latest batch from the database to get globalExitRoot and Timestamp + lastBatch := lastBatches[0] + + // Get batch before latest to get state root and local exit root + previousBatch := lastBatches[0] + if len(lastBatches) > 1 { + previousBatch = lastBatches[1] + } + + isBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, batchNumber, dbTx) + if err != nil { + return nil, err + } + if isBatchClosed { + return nil, ErrBatchAlreadyClosed + } + + // Check provided batch number is the latest in db + if lastBatch.BatchNumber != batchNumber { + return nil, ErrInvalidBatchNumber + } + forkID := GetForkIDByBatchNumber(s.cfg.ForkIDIntervals, lastBatch.BatchNumber) + + // Create Batch + processBatchRequest := &pb.ProcessBatchRequest{ + OldBatchNum: lastBatch.BatchNumber - 1, + Coinbase: lastBatch.Coinbase.String(), + BatchL2Data: batchL2Data, + OldStateRoot: previousBatch.StateRoot.Bytes(), + GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + EthTimestamp: uint64(lastBatch.Timestamp.Unix()), + UpdateMerkleTree: cTrue, + ChainId: s.cfg.ChainID, + ForkId: forkID, + } + + return s.sendBatchRequestToExecutor(ctx, processBatchRequest, caller) +} + +func (s *State) sendBatchRequestToExecutor(ctx context.Context, processBatchRequest *pb.ProcessBatchRequest, caller metrics.CallerLabel) (*pb.ProcessBatchResponse, error) { + if s.executorClient == nil { + return nil, ErrExecutorNil + } + // Send Batch to the Executor + if caller != metrics.DiscardCallerLabel { + log.Debugf("processBatch[processBatchRequest.OldBatchNum]: %v", processBatchRequest.OldBatchNum) + log.Debugf("processBatch[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) + log.Debugf("processBatch[processBatchRequest.From]: %v", processBatchRequest.From) + log.Debugf("processBatch[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) + log.Debugf("processBatch[processBatchRequest.GlobalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) + log.Debugf("processBatch[processBatchRequest.OldAccInputHash]: %v", hex.EncodeToHex(processBatchRequest.OldAccInputHash)) + log.Debugf("processBatch[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) + log.Debugf("processBatch[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) + log.Debugf("processBatch[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) + log.Debugf("processBatch[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) + log.Debugf("processBatch[processBatchRequest.ForkId]: %v", processBatchRequest.ForkId) + } + now := time.Now() + res, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) + if err != nil { + log.Errorf("Error s.executorClient.ProcessBatch: %v", err) + log.Errorf("Error s.executorClient.ProcessBatch: %s", err.Error()) + log.Errorf("Error s.executorClient.ProcessBatch response: %v", res) + } else if res.Error != executor.EXECUTOR_ERROR_NO_ERROR { + err = executor.ExecutorErr(res.Error) + s.eventLog.LogExecutorError(ctx, res.Error, processBatchRequest) + } + elapsed := time.Since(now) + if caller != metrics.DiscardCallerLabel { + metrics.ExecutorProcessingTime(string(caller), elapsed) + } + log.Infof("Batch: %d took %v to be processed by the executor ", processBatchRequest.OldBatchNum+1, elapsed) + + return res, err +} + +func (s *State) isBatchClosable(ctx context.Context, receipt ProcessingReceipt, dbTx pgx.Tx) error { + // Check if the batch that is being closed is the last batch + lastBatchNum, err := s.PostgresStorage.GetLastBatchNumber(ctx, dbTx) + if err != nil { + return err + } + if lastBatchNum != receipt.BatchNumber { + return fmt.Errorf("%w number %d, should be %d", ErrUnexpectedBatch, receipt.BatchNumber, lastBatchNum) + } + // Check if last batch is closed + isLastBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, lastBatchNum, dbTx) + if err != nil { + return err + } + if isLastBatchClosed { + return ErrBatchAlreadyClosed + } + + return nil +} + +// CloseBatch is used by sequencer to close the current batch +func (s *State) CloseBatch(ctx context.Context, receipt ProcessingReceipt, dbTx pgx.Tx) error { + if dbTx == nil { + return ErrDBTxNil + } + + err := s.isBatchClosable(ctx, receipt, dbTx) + if err != nil { + return err + } + + return s.PostgresStorage.closeBatch(ctx, receipt, dbTx) +} + +// ProcessAndStoreClosedBatch is used by the Synchronizer to add a closed batch into the data base +func (s *State) ProcessAndStoreClosedBatch(ctx context.Context, processingCtx ProcessingContext, encodedTxs []byte, dbTx pgx.Tx, caller metrics.CallerLabel) (common.Hash, error) { + // Decode transactions + decodedTransactions, _, err := DecodeTxs(encodedTxs) + if err != nil && !errors.Is(err, ErrInvalidData) { + log.Debugf("error decoding transactions: %v", err) + return common.Hash{}, err + } + + // Open the batch and process the txs + if dbTx == nil { + return common.Hash{}, ErrDBTxNil + } + if err := s.OpenBatch(ctx, processingCtx, dbTx); err != nil { + return common.Hash{}, err + } + processed, err := s.processBatch(ctx, processingCtx.BatchNumber, encodedTxs, caller, dbTx) + if err != nil { + return common.Hash{}, err + } + + // Sanity check + if len(decodedTransactions) != len(processed.Responses) { + log.Errorf("number of decoded (%d) and processed (%d) transactions do not match", len(decodedTransactions), len(processed.Responses)) + } + + // Filter unprocessed txs and decode txs to store metadata + // note that if the batch is not well encoded it will result in an empty batch (with no txs) + for i := 0; i < len(processed.Responses); i++ { + if !IsStateRootChanged(processed.Responses[i].Error) { + if executor.IsROMOutOfCountersError(processed.Responses[i].Error) { + processed.Responses = []*pb.ProcessTransactionResponse{} + break + } + + // Remove unprocessed tx + if i == len(processed.Responses)-1 { + processed.Responses = processed.Responses[:i] + decodedTransactions = decodedTransactions[:i] + } else { + processed.Responses = append(processed.Responses[:i], processed.Responses[i+1:]...) + decodedTransactions = append(decodedTransactions[:i], decodedTransactions[i+1:]...) + } + i-- + } + } + + processedBatch, err := s.convertToProcessBatchResponse(decodedTransactions, processed) + if err != nil { + return common.Hash{}, err + } + + if len(processedBatch.Responses) > 0 { + // Store processed txs into the batch + err = s.StoreTransactions(ctx, processingCtx.BatchNumber, processedBatch.Responses, dbTx) + if err != nil { + return common.Hash{}, err + } + } + + // Close batch + return common.BytesToHash(processed.NewStateRoot), s.closeBatch(ctx, ProcessingReceipt{ + BatchNumber: processingCtx.BatchNumber, + StateRoot: processedBatch.NewStateRoot, + LocalExitRoot: processedBatch.NewLocalExitRoot, + AccInputHash: processedBatch.NewAccInputHash, + BatchL2Data: encodedTxs, + }, dbTx) +} + +// GetLastBatch gets latest batch (closed or not) on the data base +func (s *State) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*Batch, error) { + batches, err := s.PostgresStorage.GetLastNBatches(ctx, 1, dbTx) + if err != nil { + return nil, err + } + if len(batches) == 0 { + return nil, ErrNotFound + } + return batches[0], nil } diff --git a/state/config.go b/state/config.go index 581be1dda9..6716335155 100644 --- a/state/config.go +++ b/state/config.go @@ -7,4 +7,7 @@ type Config struct { // ChainID is the L2 ChainID provided by the Network Config ChainID uint64 + + // ForkIdIntervals is the list of fork id intervals + ForkIDIntervals []ForkIDInterval } diff --git a/state/converters.go b/state/converters.go index 6dd17e3d8a..07fa329b8e 100644 --- a/state/converters.go +++ b/state/converters.go @@ -1,9 +1,13 @@ package state import ( + "context" "fmt" "math/big" + "time" + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/event" "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" @@ -14,44 +18,110 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// ConvertToCounters extracts ZKCounters from a ProcessBatchResponse +func ConvertToCounters(resp *pb.ProcessBatchResponse) ZKCounters { + return ZKCounters{ + CumulativeGasUsed: resp.CumulativeGasUsed, + UsedKeccakHashes: resp.CntKeccakHashes, + UsedPoseidonHashes: resp.CntPoseidonHashes, + UsedPoseidonPaddings: resp.CntPoseidonPaddings, + UsedMemAligns: resp.CntMemAligns, + UsedArithmetics: resp.CntArithmetics, + UsedBinaries: resp.CntBinaries, + UsedSteps: resp.CntSteps, + } +} + // TestConvertToProcessBatchResponse for test purposes -func TestConvertToProcessBatchResponse(txs []types.Transaction, response *pb.ProcessBatchResponse) (*ProcessBatchResponse, error) { - return convertToProcessBatchResponse(txs, response) +func (s *State) TestConvertToProcessBatchResponse(txs []types.Transaction, response *pb.ProcessBatchResponse) (*ProcessBatchResponse, error) { + return s.convertToProcessBatchResponse(txs, response) } -func convertToProcessBatchResponse(txs []types.Transaction, response *pb.ProcessBatchResponse) (*ProcessBatchResponse, error) { - responses, err := convertToProcessTransactionResponse(txs, response.Responses) +func (s *State) convertToProcessBatchResponse(txs []types.Transaction, response *pb.ProcessBatchResponse) (*ProcessBatchResponse, error) { + responses, err := s.convertToProcessTransactionResponse(txs, response.Responses) + if err != nil { + return nil, err + } + + readWriteAddresses, err := convertToReadWriteAddresses(response.ReadWriteAddresses) if err != nil { return nil, err } - isBatchProcessed := true - if len(response.Responses) > 0 { - // Check out of counters - isBatchProcessed = !(response.Responses[len(response.Responses)-1].Error == pb.Error_ERROR_OUT_OF_COUNTERS) + isExecutorLevelError := (response.Error != executor.EXECUTOR_ERROR_NO_ERROR) + isRomLevelError := false + isRomOOCError := false + + if response.Responses != nil { + for _, resp := range response.Responses { + if resp.Error != pb.RomError_ROM_ERROR_NO_ERROR { + isRomLevelError = true + break + } + } + + if len(response.Responses) > 0 { + // Check out of counters + errorToCheck := response.Responses[len(response.Responses)-1].Error + isRomOOCError = executor.IsROMOutOfCountersError(errorToCheck) + } } return &ProcessBatchResponse{ - CumulativeGasUsed: response.CumulativeGasUsed, - IsBatchProcessed: isBatchProcessed, - Responses: responses, - NewStateRoot: common.BytesToHash(response.NewStateRoot), - NewLocalExitRoot: common.BytesToHash(response.NewLocalExitRoot), - CntKeccakHashes: response.CntKeccakHashes, - CntPoseidonHashes: response.CntPoseidonHashes, - CntPoseidonPaddings: response.CntPoseidonPaddings, - CntMemAligns: response.CntMemAligns, - CntArithmetics: response.CntArithmetics, - CntBinaries: response.CntBinaries, - CntSteps: response.CntSteps, + NewStateRoot: common.BytesToHash(response.NewStateRoot), + NewAccInputHash: common.BytesToHash(response.NewAccInputHash), + NewLocalExitRoot: common.BytesToHash(response.NewLocalExitRoot), + NewBatchNumber: response.NewBatchNum, + UsedZkCounters: convertToCounters(response), + Responses: responses, + ExecutorError: executor.ExecutorErr(response.Error), + IsExecutorLevelError: isExecutorLevelError, + IsRomLevelError: isRomLevelError, + IsRomOOCError: isRomOOCError, + ReadWriteAddresses: readWriteAddresses, }, nil } -func isProcessed(err pb.Error) bool { - return err != pb.Error_ERROR_INTRINSIC_INVALID_TX && err != pb.Error_ERROR_OUT_OF_COUNTERS +// IsStateRootChanged returns true if the transaction changes the state root +func IsStateRootChanged(err pb.RomError) bool { + return !executor.IsIntrinsicError(err) && !executor.IsROMOutOfCountersError(err) +} + +func convertToReadWriteAddresses(addresses map[string]*pb.InfoReadWrite) (map[common.Address]*InfoReadWrite, error) { + results := make(map[common.Address]*InfoReadWrite, len(addresses)) + + for addr, addrInfo := range addresses { + var nonce *uint64 = nil + var balance *big.Int = nil + var ok bool + + address := common.HexToAddress(addr) + + if addrInfo.Nonce != "" { + bigNonce, ok := new(big.Int).SetString(addrInfo.Nonce, encoding.Base10) + if !ok { + log.Debugf("received nonce as string: %v", addrInfo.Nonce) + return nil, fmt.Errorf("error while parsing address nonce") + } + nonceNp := bigNonce.Uint64() + nonce = &nonceNp + } + + if addrInfo.Balance != "" { + balance, ok = new(big.Int).SetString(addrInfo.Balance, encoding.Base10) + if !ok { + log.Debugf("received balance as string: %v", addrInfo.Balance) + return nil, fmt.Errorf("error while parsing address balance") + } + } + + results[address] = &InfoReadWrite{Address: address, Nonce: nonce, Balance: balance} + } + + return results, nil } -func convertToProcessTransactionResponse(txs []types.Transaction, responses []*pb.ProcessTransactionResponse) ([]*ProcessTransactionResponse, error) { +func (s *State) convertToProcessTransactionResponse(txs []types.Transaction, responses []*pb.ProcessTransactionResponse) ([]*ProcessTransactionResponse, error) { results := make([]*ProcessTransactionResponse, 0, len(responses)) for i, response := range responses { trace, err := convertToStructLogArray(response.ExecutionTrace) @@ -66,24 +136,44 @@ func convertToProcessTransactionResponse(txs []types.Transaction, responses []*p result.GasLeft = response.GasLeft result.GasUsed = response.GasUsed result.GasRefunded = response.GasRefunded - result.Error = executor.Err(response.Error) + result.RomError = executor.RomErr(response.Error) result.CreateAddress = common.HexToAddress(response.CreateAddress) result.StateRoot = common.BytesToHash(response.StateRoot) result.Logs = convertToLog(response.Logs) - result.IsProcessed = isProcessed(response.Error) + result.ChangesStateRoot = IsStateRootChanged(response.Error) result.ExecutionTrace = *trace result.CallTrace = convertToExecutorTrace(response.CallTrace) result.Tx = txs[i] + + _, err = DecodeTx(common.Bytes2Hex(response.GetRlpTx())) + if err != nil { + timestamp := time.Now() + log.Errorf("error decoding rlp returned by executor %v at %v", err, timestamp) + + event := &event.Event{ + ReceivedAt: timestamp, + Source: event.Source_Node, + Level: event.Level_Error, + EventID: event.EventID_ExecutorRLPError, + Json: string(response.GetRlpTx()), + } + + err = s.eventLog.LogEvent(context.Background(), event) + if err != nil { + log.Errorf("error storing payload: %v", err) + } + } + results = append(results, result) - log.Debugf("ProcessTransactionResponse[TxHash]: %v", txs[i].Hash().String()) - log.Debugf("ProcessTransactionResponse[Nonce]: %v", txs[i].Nonce()) + log.Debugf("ProcessTransactionResponse[TxHash]: %v", result.TxHash) + log.Debugf("ProcessTransactionResponse[Nonce]: %v", result.Tx.Nonce()) log.Debugf("ProcessTransactionResponse[StateRoot]: %v", result.StateRoot.String()) - log.Debugf("ProcessTransactionResponse[Error]: %v", result.Error) + log.Debugf("ProcessTransactionResponse[Error]: %v", result.RomError) log.Debugf("ProcessTransactionResponse[GasUsed]: %v", result.GasUsed) log.Debugf("ProcessTransactionResponse[GasLeft]: %v", result.GasLeft) log.Debugf("ProcessTransactionResponse[GasRefunded]: %v", result.GasRefunded) - log.Debugf("ProcessTransactionResponse[IsProcessed]: %v", result.IsProcessed) + log.Debugf("ProcessTransactionResponse[ChangesStateRoot]: %v", result.ChangesStateRoot) } return results, nil @@ -137,7 +227,7 @@ func convertToStructLogArray(responses []*pb.ExecutionTraceStep) (*[]instrumenta result.Storage = convertToProperMap(response.Storage) result.Depth = int(response.Depth) result.RefundCounter = response.GasRefund - result.Err = executor.Err(response.Error) + result.Err = executor.RomErr(response.Error) results = append(results, *result) } @@ -152,7 +242,7 @@ func convertToBigIntArray(responses []string) ([]*big.Int, error) { if ok { results = append(results, result) } else { - return nil, fmt.Errorf("String %s is not valid", response) + return nil, fmt.Errorf("string %s is not valid", response) } } return results, nil @@ -203,16 +293,17 @@ func convertToInstrumentationSteps(responses []*pb.TransactionStep) []instrument step.OpCode = fakevm.OpCode(response.Op).String() step.Refund = fmt.Sprint(response.GasRefund) step.Op = fmt.Sprint(response.Op) - err := executor.Err(response.Error) + err := executor.RomErr(response.Error) if err != nil { step.Error = err.Error() } step.Contract = convertToInstrumentationContract(response.Contract) step.GasCost = fmt.Sprint(response.GasCost) step.Stack = response.Stack - step.Memory = convertByteArrayToStringArray(response.Memory) - step.ReturnData = string(response.ReturnData) - + step.Memory = make([]byte, len(response.Memory)) + copy(step.Memory, response.Memory) + step.ReturnData = make([]byte, len(response.ReturnData)) + copy(step.ReturnData, response.ReturnData) results = append(results, *step) } return results @@ -228,10 +319,15 @@ func convertToInstrumentationContract(response *pb.Contract) instrumentation.Con } } -func convertByteArrayToStringArray(responses []byte) []string { - results := make([]string, 0, len(responses)) - for _, response := range responses { - results = append(results, string(response)) +func convertToCounters(resp *pb.ProcessBatchResponse) ZKCounters { + return ZKCounters{ + CumulativeGasUsed: resp.CumulativeGasUsed, + UsedKeccakHashes: resp.CntKeccakHashes, + UsedPoseidonHashes: resp.CntPoseidonHashes, + UsedPoseidonPaddings: resp.CntPoseidonPaddings, + UsedMemAligns: resp.CntMemAligns, + UsedArithmetics: resp.CntArithmetics, + UsedBinaries: resp.CntBinaries, + UsedSteps: resp.CntSteps, } - return results } diff --git a/state/crypto.go b/state/crypto.go index 1e31420b95..72e6a1f102 100644 --- a/state/crypto.go +++ b/state/crypto.go @@ -16,8 +16,11 @@ var ( func CheckSignature(tx types.Transaction) error { // Check Signature v, r, s := tx.RawSignatureValues() - plainV := byte(v.Uint64() - 35 - 2*(tx.ChainId().Uint64())) - + plainV := byte(0) + chainID := tx.ChainId().Uint64() + if chainID != 0 { + plainV = byte(v.Uint64() - 35 - 2*(chainID)) + } if !crypto.ValidateSignatureValues(plainV, r, s, false) { return ErrInvalidSig } diff --git a/state/errors.go b/state/errors.go index f8664cf021..606ad910f7 100644 --- a/state/errors.go +++ b/state/errors.go @@ -10,6 +10,8 @@ import ( var ( // ErrInvalidBatchHeader indicates the batch header is invalid ErrInvalidBatchHeader = errors.New("invalid batch header") + // ErrUnexpectedBatch indicates that the batch is unexpected + ErrUnexpectedBatch = errors.New("unexpected batch") // ErrStateNotSynchronized indicates the state database may be empty ErrStateNotSynchronized = errors.New("state not synchronized") // ErrNotFound indicates an object has not been found for the search criteria used @@ -44,6 +46,19 @@ var ( // ErrInsufficientFunds is returned if the total cost of executing a transaction // is higher than the balance of the user's account. ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value") + // ErrExecutorNil indicates that the method requires an executor that is not nil + ErrExecutorNil = errors.New("the method requires an executor that is not nil") + // ErrStateTreeNil indicates that the method requires a state tree that is not nil + ErrStateTreeNil = errors.New("the method requires a state tree that is not nil") + // ErrUnsupportedDuration is returned if the provided unit for a time + // interval is not supported by our conversion mechanism. + ErrUnsupportedDuration = errors.New("unsupported time duration") + // ErrInvalidData is the error when the raw txs is unexpected + ErrInvalidData = errors.New("invalid data") + // ErrBatchResourceBytesUnderflow happens when the batch runs out of Bytes + ErrBatchResourceBytesUnderflow = NewBatchRemainingResourcesUnderflowError(nil, "Bytes") + + zkCounterErrPrefix = "ZKCounter: " ) func constructErrorFromRevert(err error, returnValue []byte) error { @@ -54,3 +69,35 @@ func constructErrorFromRevert(err error, returnValue []byte) error { return fmt.Errorf("%w: %s", err, revertErrMsg) } + +// GetZKCounterError returns the error associated with the zkCounter +func GetZKCounterError(name string) error { + return errors.New(zkCounterErrPrefix + name) +} + +// BatchRemainingResourcesUnderflowError happens when the execution of a batch runs out of counters +type BatchRemainingResourcesUnderflowError struct { + Message string + Code int + Err error + ResourceName string +} + +// Error returns the error message +func (b BatchRemainingResourcesUnderflowError) Error() string { + return constructErrorMsg(b.ResourceName) +} + +// NewBatchRemainingResourcesUnderflowError creates a new BatchRemainingResourcesUnderflowError +func NewBatchRemainingResourcesUnderflowError(err error, resourceName string) error { + return &BatchRemainingResourcesUnderflowError{ + Message: constructErrorMsg(resourceName), + Code: 1, + Err: err, + ResourceName: resourceName, + } +} + +func constructErrorMsg(resourceName string) string { + return fmt.Sprintf("underflow of remaining resources for current batch. Resource %s", resourceName) +} diff --git a/state/fakedb.go b/state/fakedb.go index e47b223801..f204f8b9b3 100644 --- a/state/fakedb.go +++ b/state/fakedb.go @@ -6,6 +6,8 @@ import ( "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" ) // FakeDB is the implementation of the fakeevm.FakeDB interface @@ -19,6 +21,21 @@ func (f *FakeDB) SetStateRoot(stateRoot []byte) { f.stateRoot = stateRoot } +// CreateAccount not implemented +func (f *FakeDB) CreateAccount(common.Address) { + log.Error("FakeDB: CreateAccount method not implemented") +} + +// SubBalance not implemented +func (f *FakeDB) SubBalance(common.Address, *big.Int) { + log.Error("FakeDB: SubBalance method not implemented") +} + +// AddBalance not implemented +func (f *FakeDB) AddBalance(common.Address, *big.Int) { + log.Error("FakeDB: AddBalance method not implemented") +} + // GetBalance returns the balance of the given address. func (f *FakeDB) GetBalance(address common.Address) *big.Int { ctx := context.Background() @@ -46,6 +63,23 @@ func (f *FakeDB) GetNonce(address common.Address) uint64 { return nonce.Uint64() } +// SetNonce not implemented +func (f *FakeDB) SetNonce(common.Address, uint64) { + log.Error("FakeDB: SetNonce method not implemented") +} + +// GetCodeHash gets the hash for the code at a given address +func (f *FakeDB) GetCodeHash(address common.Address) common.Hash { + ctx := context.Background() + hash, err := f.State.GetTree().GetCodeHash(ctx, address, f.stateRoot) + if err != nil { + log.Errorf("error on FakeDB GetCodeHash for address %v, err: %v", address, err) + } + + log.Debugf("FakeDB GetCodeHash for address %v => %v", address, common.BytesToHash(hash)) + return common.BytesToHash(hash) +} + // GetCode returns the SC code of the given address. func (f *FakeDB) GetCode(address common.Address) []byte { ctx := context.Background() @@ -59,6 +93,38 @@ func (f *FakeDB) GetCode(address common.Address) []byte { return code } +// SetCode not implemented +func (f *FakeDB) SetCode(common.Address, []byte) { + log.Error("FakeDB: SetCode method not implemented") +} + +// GetCodeSize get address code size +func (f *FakeDB) GetCodeSize(address common.Address) int { + return len(f.GetCode(address)) +} + +// AddRefund not implemented +func (f *FakeDB) AddRefund(uint64) { + log.Error("FakeDB: AddRefund method not implemented") +} + +// SubRefund not implemented +func (f *FakeDB) SubRefund(uint64) { + log.Error("FakeDB: SubRefund method not implemented") +} + +// GetRefund not implemented +func (f *FakeDB) GetRefund() uint64 { + log.Error("FakeDB: GetRefund method not implemented") + return 0 +} + +// GetCommittedState not implemented +func (f *FakeDB) GetCommittedState(common.Address, common.Hash) common.Hash { + log.Error("FakeDB: GetCommittedState method not implemented") + return ZeroHash +} + // GetState retrieves a value from the given account's storage trie. func (f *FakeDB) GetState(address common.Address, hash common.Hash) common.Hash { ctx := context.Background() @@ -73,20 +139,94 @@ func (f *FakeDB) GetState(address common.Address, hash common.Hash) common.Hash return common.BytesToHash(storage.Bytes()) } -// Exist determines if the given address is in use. +// SetState not implemented +func (f *FakeDB) SetState(common.Address, common.Hash, common.Hash) { + log.Error("FakeDB: SetState method not implemented") +} + +// GetTransientState not implemented +func (f *FakeDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { + log.Error("FakeDB: GetTransientState method not implemented") + return ZeroHash +} + +// SetTransientState not implemented +func (f *FakeDB) SetTransientState(addr common.Address, key, value common.Hash) { + log.Error("FakeDB: SetTransientState method not implemented") +} + +// Suicide not implemented +func (f *FakeDB) Suicide(common.Address) bool { + log.Error("FakeDB: Suicide method not implemented") + return false +} + +// HasSuicided not implemented +func (f *FakeDB) HasSuicided(common.Address) bool { + log.Error("FakeDB: HasSuicided method not implemented") + return false +} + +// Exist reports whether the given account exists in state. +// Notably this should also return true for suicided accounts. func (f *FakeDB) Exist(address common.Address) bool { return !(f.GetNonce(address) == 0 && f.GetBalance(address).Int64() == 0 && f.GetCodeHash(address) == ZeroHash) } -// GetCodeHash gets the hash for the code at a given address -func (f *FakeDB) GetCodeHash(address common.Address) common.Hash { - ctx := context.Background() - hash, err := f.State.GetTree().GetCodeHash(ctx, address, f.stateRoot) +// Empty returns whether the given account is empty. Empty +// is defined according to EIP161 (balance = nonce = code = 0). +func (f *FakeDB) Empty(address common.Address) bool { + return !(f.GetNonce(address) == 0 && f.GetBalance(address).Int64() == 0 && f.GetCodeHash(address) == ZeroHash) +} - if err != nil { - log.Errorf("error on FakeDB GetCodeHash for address %v, err: %v", address, err) - } +// AddressInAccessList not implemented +func (f *FakeDB) AddressInAccessList(addr common.Address) bool { + log.Error("FakeDB: AddressInAccessList method not implemented") + return false +} - log.Debugf("FakeDB GetCodeHash for address %v => %v", address, common.BytesToHash(hash)) - return common.BytesToHash(hash) +// SlotInAccessList not implemented +func (f *FakeDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { + log.Error("FakeDB: SlotInAccessList method not implemented") + return false, false +} + +// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform + +// AddAddressToAccessList not implemented// even if the feature/fork is not active yet +func (f *FakeDB) AddAddressToAccessList(addr common.Address) { + log.Error("FakeDB: AddAddressToAccessList method not implemented") +} + +// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform + +// AddSlotToAccessList not implemented// even if the feature/fork is not active yet +func (f *FakeDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { + log.Error("FakeDB: AddSlotToAccessList method not implemented") +} + +// Prepare not implemented +func (f *FakeDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) { + log.Error("FakeDB: Prepare method not implemented") +} + +// RevertToSnapshot not implemented +func (f *FakeDB) RevertToSnapshot(int) { + log.Error("FakeDB: RevertToSnapshot method not implemented") +} + +// Snapshot not implemented +func (f *FakeDB) Snapshot() int { + log.Error("FakeDB: Snapshot method not implemented") + return 0 +} + +// AddLog not implemented +func (f *FakeDB) AddLog(*types.Log) { + log.Error("FakeDB: AddLog method not implemented") +} + +// AddPreimage not implemented +func (f *FakeDB) AddPreimage(common.Hash, []byte) { + log.Error("FakeDB: AddPreimage method not implemented") } diff --git a/state/forcedbatch.go b/state/forcedbatch.go index 3e54e808fb..3170e9bf5f 100644 --- a/state/forcedbatch.go +++ b/state/forcedbatch.go @@ -9,7 +9,6 @@ import ( // ForcedBatch represents a ForcedBatch type ForcedBatch struct { BlockNumber uint64 - BatchNumber *uint64 ForcedBatchNumber uint64 Sequencer common.Address GlobalExitRoot common.Hash diff --git a/state/forkid.go b/state/forkid.go new file mode 100644 index 0000000000..2337dee0cf --- /dev/null +++ b/state/forkid.go @@ -0,0 +1,34 @@ +package state + +import "github.com/0xPolygonHermez/zkevm-node/log" + +// ForkIDInterval is a fork id interval +type ForkIDInterval struct { + FromBatchNumber uint64 + ToBatchNumber uint64 + ForkId uint64 + Version string +} + +// UpdateForkIDIntervals updates the forkID intervals +func (s *State) UpdateForkIDIntervals(intervals []ForkIDInterval) { + log.Infof("Updating forkIDs. Setting %d forkIDs", len(intervals)) + s.cfg.ForkIDIntervals = intervals +} + +// GetForkIDByBatchNumber returns the fork id for a given batch number +func GetForkIDByBatchNumber(intervals []ForkIDInterval, batchNumber uint64) uint64 { + for _, interval := range intervals { + if batchNumber >= interval.FromBatchNumber && batchNumber <= interval.ToBatchNumber { + return interval.ForkId + } + } + + // If not found return the last fork id + return intervals[len(intervals)-1].ForkId +} + +// GetForkIDByBatchNumber returns the fork id for the given batch number +func (s *State) GetForkIDByBatchNumber(batchNumber uint64) uint64 { + return GetForkIDByBatchNumber(s.cfg.ForkIDIntervals, batchNumber) +} diff --git a/state/genesis.go b/state/genesis.go index 311a444e2e..ef38a5e6cb 100644 --- a/state/genesis.go +++ b/state/genesis.go @@ -1,11 +1,26 @@ package state -import "github.com/ethereum/go-ethereum/common" +import ( + "context" + "fmt" + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/merkletree" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/trie" + "github.com/jackc/pgx/v4" +) // Genesis contains the information to populate state on creation type Genesis struct { - Root common.Hash - Actions []*GenesisAction + // GenesisBlockNum is the block number where the polygonZKEVM smc was deployed + GenesisBlockNum uint64 + Root common.Hash + GenesisActions []*GenesisAction } // GenesisAction represents one of the values set on the SMT during genesis. @@ -18,3 +33,144 @@ type GenesisAction struct { Value string `json:"value"` Root string `json:"root"` } + +// SetGenesis populates state with genesis information +func (s *State) SetGenesis(ctx context.Context, block Block, genesis Genesis, dbTx pgx.Tx) ([]byte, error) { + var ( + root common.Hash + newRoot []byte + err error + ) + if dbTx == nil { + return newRoot, ErrDBTxNil + } + if s.tree == nil { + return newRoot, ErrStateTreeNil + } + + for _, action := range genesis.GenesisActions { + address := common.HexToAddress(action.Address) + switch action.Type { + case int(merkletree.LeafTypeBalance): + balance, err := encoding.DecodeBigIntHexOrDecimal(action.Value) + if err != nil { + return newRoot, err + } + newRoot, _, err = s.tree.SetBalance(ctx, address, balance, newRoot) + if err != nil { + return newRoot, err + } + case int(merkletree.LeafTypeNonce): + nonce, err := encoding.DecodeBigIntHexOrDecimal(action.Value) + if err != nil { + return newRoot, err + } + newRoot, _, err = s.tree.SetNonce(ctx, address, nonce, newRoot) + if err != nil { + return newRoot, err + } + case int(merkletree.LeafTypeCode): + code, err := hex.DecodeHex(action.Bytecode) + if err != nil { + return newRoot, fmt.Errorf("could not decode SC bytecode for address %q: %v", address, err) + } + newRoot, _, err = s.tree.SetCode(ctx, address, code, newRoot) + if err != nil { + return newRoot, err + } + case int(merkletree.LeafTypeStorage): + // Parse position and value + positionBI, err := encoding.DecodeBigIntHexOrDecimal(action.StoragePosition) + if err != nil { + return newRoot, err + } + valueBI, err := encoding.DecodeBigIntHexOrDecimal(action.Value) + if err != nil { + return newRoot, err + } + // Store + newRoot, _, err = s.tree.SetStorageAt(ctx, address, positionBI, valueBI, newRoot) + if err != nil { + return newRoot, err + } + case int(merkletree.LeafTypeSCLength): + log.Debug("Skipped genesis action of type merkletree.LeafTypeSCLength, these actions will be handled as part of merkletree.LeafTypeCode actions") + default: + return newRoot, fmt.Errorf("unknown genesis action type %q", action.Type) + } + } + + root.SetBytes(newRoot) + + // flush state db + err = s.tree.Flush(ctx) + if err != nil { + log.Errorf("error flushing state tree after genesis: %v", err) + return newRoot, err + } + + // store L1 block related to genesis batch + err = s.AddBlock(ctx, &block, dbTx) + if err != nil { + return newRoot, err + } + + // store genesis batch + batch := Batch{ + BatchNumber: 0, + Coinbase: ZeroAddress, + BatchL2Data: nil, + StateRoot: root, + LocalExitRoot: ZeroHash, + Timestamp: block.ReceivedAt, + Transactions: []types.Transaction{}, + GlobalExitRoot: ZeroHash, + ForcedBatchNum: nil, + } + + err = s.storeGenesisBatch(ctx, batch, dbTx) + if err != nil { + return newRoot, err + } + + // mark the genesis batch as virtualized + virtualBatch := &VirtualBatch{ + BatchNumber: batch.BatchNumber, + TxHash: ZeroHash, + Coinbase: ZeroAddress, + BlockNumber: block.BlockNumber, + } + err = s.AddVirtualBatch(ctx, virtualBatch, dbTx) + if err != nil { + return newRoot, err + } + + // mark the genesis batch as verified/consolidated + verifiedBatch := &VerifiedBatch{ + BatchNumber: batch.BatchNumber, + TxHash: ZeroHash, + Aggregator: ZeroAddress, + BlockNumber: block.BlockNumber, + } + err = s.AddVerifiedBatch(ctx, verifiedBatch, dbTx) + if err != nil { + return newRoot, err + } + + // store L2 genesis block + header := &types.Header{ + Number: big.NewInt(0), + ParentHash: ZeroHash, + Coinbase: ZeroAddress, + Root: root, + Time: uint64(block.ReceivedAt.Unix()), + } + rootHex := root.Hex() + log.Info("Genesis root ", rootHex) + + receipts := []*types.Receipt{} + l2Block := types.NewBlock(header, []*types.Transaction{}, []*types.Header{}, receipts, &trie.StackTrie{}) + l2Block.ReceivedAt = block.ReceivedAt + + return newRoot, s.AddL2Block(ctx, batch.BatchNumber, l2Block, receipts, dbTx) +} diff --git a/state/genesis_test.go b/state/genesis_test.go index 4be91d5d7c..1010515912 100644 --- a/state/genesis_test.go +++ b/state/genesis_test.go @@ -87,7 +87,7 @@ func genesisCase(t *testing.T, tv genesisTestVectorReader) { require.NoError(t, err) actions := genesisparser.GenesisTest2Actions(tv.GenesisAccountTest()) genesis := state.Genesis{ - Actions: actions, + GenesisActions: actions, } ctx := context.Background() dbTx, err := testState.BeginStateTransaction(ctx) diff --git a/state/globalexitroot.go b/state/globalexitroot.go index f853d61889..f22160e57c 100644 --- a/state/globalexitroot.go +++ b/state/globalexitroot.go @@ -1,16 +1,16 @@ package state import ( - "math/big" + "time" "github.com/ethereum/go-ethereum/common" ) // GlobalExitRoot struct type GlobalExitRoot struct { - BlockNumber uint64 - GlobalExitRootNum *big.Int - MainnetExitRoot common.Hash - RollupExitRoot common.Hash - GlobalExitRoot common.Hash + BlockNumber uint64 + Timestamp time.Time + MainnetExitRoot common.Hash + RollupExitRoot common.Hash + GlobalExitRoot common.Hash } diff --git a/state/helper.go b/state/helper.go index ea7ea20e99..c3a1cacd16 100644 --- a/state/helper.go +++ b/state/helper.go @@ -5,16 +5,19 @@ import ( "math/big" "strconv" - "github.com/0xPolygonHermez/zkevm-node/encoding" "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" ) -const ether155V = 27 +const ( + double = 2 + ether155V = 27 + etherPre155V = 35 +) -// EncodeTransactions RLP encodes the given transactions. +// EncodeTransactions RLP encodes the given transactions func EncodeTransactions(txs []types.Transaction) ([]byte, error) { var batchL2Data []byte @@ -25,16 +28,22 @@ func EncodeTransactions(txs []types.Transaction) ([]byte, error) { nonce, gasPrice, gas, to, value, data, chainID := tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.ChainId() log.Debug(nonce, " ", gasPrice, " ", gas, " ", to, " ", value, " ", len(data), " ", chainID) - txCodedRlp, err := rlp.EncodeToBytes([]interface{}{ + rlpFieldsToEncode := []interface{}{ nonce, gasPrice, gas, to, value, data, - chainID, uint(0), uint(0), - }) + } + + if tx.ChainId().Uint64() > 0 { + rlpFieldsToEncode = append(rlpFieldsToEncode, chainID) + rlpFieldsToEncode = append(rlpFieldsToEncode, uint(0)) + rlpFieldsToEncode = append(rlpFieldsToEncode, uint(0)) + } + txCodedRlp, err := rlp.EncodeToBytes(rlpFieldsToEncode) if err != nil { return nil, err } @@ -54,8 +63,14 @@ func EncodeTransactions(txs []types.Transaction) ([]byte, error) { return batchL2Data, nil } +// EncodeTransaction RLP encodes the given transaction +func EncodeTransaction(tx types.Transaction) ([]byte, error) { + transactions := []types.Transaction{tx} + return EncodeTransactions(transactions) +} + // EncodeUnsignedTransaction RLP encodes the given unsigned transaction -func EncodeUnsignedTransaction(tx types.Transaction, chainID uint64) ([]byte, error) { +func EncodeUnsignedTransaction(tx types.Transaction, chainID uint64, forcedNonce *uint64) ([]byte, error) { v, _ := new(big.Int).SetString("0x1c", 0) r, _ := new(big.Int).SetString("0xa54492cfacf71aef702421b7fbc70636537a7b2fbe5718c5ed970a001bb7756b", 0) s, _ := new(big.Int).SetString("0x2e9fb27acc75955b898f0b12ec52aa34bf08f01db654374484b80bf12f0d841e", 0) @@ -65,6 +80,11 @@ func EncodeUnsignedTransaction(tx types.Transaction, chainID uint64) ([]byte, er nonce, gasPrice, gas, to, value, data, chainID := tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID //nolint:gomnd log.Debug(nonce, " ", gasPrice, " ", gas, " ", to, " ", value, " ", len(data), " ", chainID) + if forcedNonce != nil { + nonce = *forcedNonce + log.Debug("Forced nonce: ", nonce) + } + txCodedRlp, err := rlp.EncodeToBytes([]interface{}{ nonce, gasPrice, @@ -91,67 +111,87 @@ func EncodeUnsignedTransaction(tx types.Transaction, chainID uint64) ([]byte, er return txData, nil } -// DecodeTxs extracts Tansactions for its encoded form +// DecodeTxs extracts Transactions for its encoded form func DecodeTxs(txsData []byte) ([]types.Transaction, []byte, error) { // Process coded txs - var pos int64 + var pos uint64 var txs []types.Transaction const ( - headerByteLength = 1 - sLength = 32 - rLength = 32 - vLength = 1 - c0 = 192 // 192 is c0. This value is defined by the rlp protocol - ff = 255 // max value of rlp header - shortRlp = 55 // length of the short rlp codification - f7 = 247 // 192 + 55 = c0 + shortRlp - etherNewV = 35 - mul2 = 2 + headerByteLength uint64 = 1 + sLength uint64 = 32 + rLength uint64 = 32 + vLength uint64 = 1 + c0 uint64 = 192 // 192 is c0. This value is defined by the rlp protocol + ff uint64 = 255 // max value of rlp header + shortRlp uint64 = 55 // length of the short rlp codification + f7 uint64 = 247 // 192 + 55 = c0 + shortRlp ) - txDataLength := len(txsData) + txDataLength := uint64(len(txsData)) if txDataLength == 0 { return txs, txsData, nil } - for pos < int64(txDataLength) { - num, err := strconv.ParseInt(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, encoding.BitSize64) + for pos < txDataLength { + num, err := strconv.ParseUint(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, hex.BitSize64) if err != nil { log.Debug("error parsing header length: ", err) - return []types.Transaction{}, []byte{}, err + return []types.Transaction{}, txsData, err } // First byte is the length and must be ignored - len := num - c0 - if len > shortRlp { // If rlp is bigger than length 55 + if num < c0 { + log.Debugf("error num < c0 : %d, %d", num, c0) + return []types.Transaction{}, txsData, ErrInvalidData + } + length := uint64(num - c0) + if length > shortRlp { // If rlp is bigger than length 55 // n is the length of the rlp data without the header (1 byte) for example "0xf7" - n, err := strconv.ParseInt(hex.EncodeToString(txsData[pos+1:pos+1+num-f7]), hex.Base, encoding.BitSize64) // +1 is the header. For example 0xf7 + if (pos + 1 + num - f7) > txDataLength { + log.Debug("error parsing length: ", err) + return []types.Transaction{}, txsData, err + } + n, err := strconv.ParseUint(hex.EncodeToString(txsData[pos+1:pos+1+num-f7]), hex.Base, hex.BitSize64) // +1 is the header. For example 0xf7 if err != nil { log.Debug("error parsing length: ", err) - return []types.Transaction{}, []byte{}, err + return []types.Transaction{}, txsData, err + } + if n+num < f7 { + log.Debug("error n + num < f7: ", err) + return []types.Transaction{}, txsData, ErrInvalidData } - len = n + num - f7 // num - f7 is the header. For example 0xf7 + length = n + num - f7 // num - f7 is the header. For example 0xf7 } - fullDataTx := txsData[pos : pos+len+rLength+sLength+vLength+headerByteLength] - txInfo := txsData[pos : pos+len+headerByteLength] - r := txsData[pos+len+headerByteLength : pos+len+rLength+headerByteLength] - s := txsData[pos+len+rLength+headerByteLength : pos+len+rLength+sLength+headerByteLength] - v := txsData[pos+len+rLength+sLength+headerByteLength : pos+len+rLength+sLength+vLength+headerByteLength] + endPos := pos + length + rLength + sLength + vLength + headerByteLength - pos = pos + len + rLength + sLength + vLength + headerByteLength + if endPos > txDataLength { + err := fmt.Errorf("endPos %d is bigger than txDataLength %d", endPos, txDataLength) + log.Debug("error parsing header: ", err) + return []types.Transaction{}, txsData, ErrInvalidData + } + + fullDataTx := txsData[pos:endPos] + txInfo := txsData[pos : pos+length+headerByteLength] + rData := txsData[pos+length+headerByteLength : pos+length+rLength+headerByteLength] + sData := txsData[pos+length+rLength+headerByteLength : pos+length+rLength+sLength+headerByteLength] + vData := txsData[pos+length+rLength+sLength+headerByteLength : endPos] + + pos = endPos - // Decode tx - var tx types.LegacyTx - err = rlp.DecodeBytes(txInfo, &tx) + // Decode rlpFields + var rlpFields [][]byte + err = rlp.DecodeBytes(txInfo, &rlpFields) if err != nil { - log.Debug("error decoding tx bytes: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo), "\n Txs received: ", hex.EncodeToString(txsData)) - return []types.Transaction{}, []byte{}, err + log.Error("error decoding tx Bytes: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo), "\n Txs received: ", hex.EncodeToString(txsData)) + return []types.Transaction{}, txsData, ErrInvalidData } - //tx.V = v-27+chainId*2+35 - tx.V = new(big.Int).Add(new(big.Int).Sub(new(big.Int).SetBytes(v), big.NewInt(ether155V)), new(big.Int).Add(new(big.Int).Mul(tx.V, big.NewInt(mul2)), big.NewInt(etherNewV))) - tx.R = new(big.Int).SetBytes(r) - tx.S = new(big.Int).SetBytes(s) + legacyTx, err := RlpFieldsToLegacyTx(rlpFields, vData, rData, sData) + if err != nil { + log.Debug("error creating tx from rlp fields: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo), "\n Txs received: ", hex.EncodeToString(txsData)) + return []types.Transaction{}, txsData, err + } - txs = append(txs, *types.NewTx(&tx)) + tx := types.NewTx(legacyTx) + txs = append(txs, *tx) } return txs, txsData, nil } @@ -192,7 +232,7 @@ func generateReceipt(blockNumber *big.Int, processedTx *ProcessTransactionRespon for i := 0; i < len(receipt.Logs); i++ { receipt.Logs[i].TxHash = processedTx.Tx.Hash() } - if processedTx.Error == nil { + if processedTx.RomError == nil { receipt.Status = types.ReceiptStatusSuccessful } else { receipt.Status = types.ReceiptStatusFailed @@ -200,3 +240,26 @@ func generateReceipt(blockNumber *big.Int, processedTx *ProcessTransactionRespon return receipt } + +func toPostgresInterval(duration string) (string, error) { + unit := duration[len(duration)-1] + var pgUnit string + + switch unit { + case 's': + pgUnit = "second" + case 'm': + pgUnit = "minute" + case 'h': + pgUnit = "hour" + default: + return "", ErrUnsupportedDuration + } + + isMoreThanOne := duration[0] != '1' || len(duration) > 2 //nolint:gomnd + if isMoreThanOne { + pgUnit = pgUnit + "s" + } + + return fmt.Sprintf("%s %s", duration[:len(duration)-1], pgUnit), nil +} diff --git a/state/helper_test.go b/state/helper_test.go new file mode 100644 index 0000000000..10229ae121 --- /dev/null +++ b/state/helper_test.go @@ -0,0 +1,99 @@ +package state_test + +import ( + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func init() { + log.Init(log.Config{ + Level: "debug", + Outputs: []string{"stderr"}, + }) +} + +func TestDecodeRandomBatchL2Data(t *testing.T) { + randomData := []byte("Random data") + txs, _, err := state.DecodeTxs(randomData) + require.Error(t, err) + assert.Equal(t, []types.Transaction{}, txs) + t.Log("Txs decoded 1: ", txs) + + randomData = []byte("Esto es autentica basura") + txs, _, err = state.DecodeTxs(randomData) + require.Error(t, err) + assert.Equal(t, []types.Transaction{}, txs) + t.Log("Txs decoded 2: ", txs) + + randomData = []byte("beef") + txs, _, err = state.DecodeTxs(randomData) + require.Error(t, err) + assert.Equal(t, []types.Transaction{}, txs) + t.Log("Txs decoded 3: ", txs) +} + +func TestDecodePre155BatchL2Data(t *testing.T) { + pre155, err := hex.DecodeString("e480843b9aca00826163941275fbb540c8efc58b812ba83b0d0b8b9917ae98808464fbb77cb7d2a666860f3c6b8f5ef96f86c7ec5562e97fd04c2e10f3755ff3a0456f9feb246df95217bf9082f84f9e40adb0049c6664a5bb4c9cbe34ab1a73e77bab26ed1b") + require.NoError(t, err) + txs, _, err := state.DecodeTxs(pre155) + require.NoError(t, err) + t.Log("Txs decoded: ", txs, len(txs)) + assert.Equal(t, 1, len(txs)) + v, r, s := txs[0].RawSignatureValues() + assert.Equal(t, "0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98", txs[0].To().String()) + assert.Equal(t, "1b", fmt.Sprintf("%x", v)) + assert.Equal(t, "b7d2a666860f3c6b8f5ef96f86c7ec5562e97fd04c2e10f3755ff3a0456f9feb", fmt.Sprintf("%x", r)) + assert.Equal(t, "246df95217bf9082f84f9e40adb0049c6664a5bb4c9cbe34ab1a73e77bab26ed", fmt.Sprintf("%x", s)) + assert.Equal(t, uint64(24931), txs[0].Gas()) + assert.Equal(t, "64fbb77c", hex.EncodeToString(txs[0].Data())) + assert.Equal(t, uint64(0), txs[0].Nonce()) + assert.Equal(t, new(big.Int).SetUint64(1000000000), txs[0].GasPrice()) + + pre155, err = hex.DecodeString("e580843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae988084159278193d7bcd98c00060650f12c381cc2d4f4cc8abf54059aecd2c7aabcfcdd191ba6827b1e72f0eb0b8d5daae64962f4aafde7853e1c102de053edbedf066e6e3c2dc1b") + require.NoError(t, err) + txs, _, err = state.DecodeTxs(pre155) + require.NoError(t, err) + t.Log("Txs decoded: ", txs) + assert.Equal(t, 1, len(txs)) + assert.Equal(t, "0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98", txs[0].To().String()) + assert.Equal(t, uint64(0), txs[0].Nonce()) + assert.Equal(t, big.NewInt(0), txs[0].Value()) + assert.Equal(t, "15927819", hex.EncodeToString(txs[0].Data())) + assert.Equal(t, uint64(100000), txs[0].Gas()) + assert.Equal(t, new(big.Int).SetUint64(1000000000), txs[0].GasPrice()) +} + +func TestDecodePre155Tx(t *testing.T) { + pre155 := "0xf86780843b9aca00826163941275fbb540c8efc58b812ba83b0d0b8b9917ae98808464fbb77c1ba0b7d2a666860f3c6b8f5ef96f86c7ec5562e97fd04c2e10f3755ff3a0456f9feba0246df95217bf9082f84f9e40adb0049c6664a5bb4c9cbe34ab1a73e77bab26ed" + tx, err := state.DecodeTx(pre155) + require.NoError(t, err) + t.Log("Txs decoded: ", tx) + v, r, s := tx.RawSignatureValues() + assert.Equal(t, "0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98", tx.To().String()) + assert.Equal(t, "1b", fmt.Sprintf("%x", v)) + assert.Equal(t, "b7d2a666860f3c6b8f5ef96f86c7ec5562e97fd04c2e10f3755ff3a0456f9feb", fmt.Sprintf("%x", r)) + assert.Equal(t, "246df95217bf9082f84f9e40adb0049c6664a5bb4c9cbe34ab1a73e77bab26ed", fmt.Sprintf("%x", s)) + assert.Equal(t, uint64(24931), tx.Gas()) + assert.Equal(t, "64fbb77c", hex.EncodeToString(tx.Data())) + assert.Equal(t, uint64(0), tx.Nonce()) + assert.Equal(t, new(big.Int).SetUint64(1000000000), tx.GasPrice()) +} + +func TestEncodePre155BatchL2Data(t *testing.T) { + pre155, err := hex.DecodeString("e480843b9aca00826163941275fbb540c8efc58b812ba83b0d0b8b9917ae98808464fbb77cb7d2a666860f3c6b8f5ef96f86c7ec5562e97fd04c2e10f3755ff3a0456f9feb246df95217bf9082f84f9e40adb0049c6664a5bb4c9cbe34ab1a73e77bab26ed1b") + require.NoError(t, err) + txs, _, err := state.DecodeTxs(pre155) + require.NoError(t, err) + rawtxs, err := state.EncodeTransactions(txs) + require.NoError(t, err) + t.Log("Txs decoded: ", txs, len(txs)) + assert.Equal(t, pre155, rawtxs) +} diff --git a/state/l2block.go b/state/l2block.go new file mode 100644 index 0000000000..3d6021717c --- /dev/null +++ b/state/l2block.go @@ -0,0 +1,111 @@ +package state + +import ( + "context" + "errors" + "math/big" + "sync" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/ethereum/go-ethereum/core/types" +) + +// NewL2BlockEventHandler represent a func that will be called by the +// state when a NewL2BlockEvent is triggered +type NewL2BlockEventHandler func(e NewL2BlockEvent) + +// NewL2BlockEvent is a struct provided from the state to the NewL2BlockEventHandler +// when a new l2 block is detected with data related to this new l2 block. +type NewL2BlockEvent struct { + Block types.Block +} + +// PrepareWebSocket allows the RPC to prepare ws +func (s *State) PrepareWebSocket() { + lastL2Block, err := s.PostgresStorage.GetLastL2Block(context.Background(), nil) + if errors.Is(err, ErrStateNotSynchronized) { + lastL2Block = types.NewBlockWithHeader(&types.Header{Number: big.NewInt(0)}) + } else if err != nil { + log.Fatalf("failed to load the last l2 block: %v", err) + } + s.lastL2BlockSeen = *lastL2Block + go s.monitorNewL2Blocks() + go s.handleEvents() +} + +// RegisterNewL2BlockEventHandler add the provided handler to the list of handlers +// that will be triggered when a new l2 block event is triggered +func (s *State) RegisterNewL2BlockEventHandler(h NewL2BlockEventHandler) { + log.Info("new l2 block event handler registered") + s.newL2BlockEventHandlers = append(s.newL2BlockEventHandlers, h) +} + +func (s *State) handleEvents() { + for newL2BlockEvent := range s.newL2BlockEvents { + if len(s.newL2BlockEventHandlers) == 0 { + continue + } + + wg := sync.WaitGroup{} + for _, handler := range s.newL2BlockEventHandlers { + wg.Add(1) + go func(h NewL2BlockEventHandler) { + defer func() { + wg.Done() + if r := recover(); r != nil { + log.Errorf("failed and recovered in NewL2BlockEventHandler: %v", r) + } + }() + h(newL2BlockEvent) + }(handler) + } + wg.Wait() + } +} + +func (s *State) monitorNewL2Blocks() { + waitNextCycle := func() { + time.Sleep(1 * time.Second) + } + + for { + if len(s.newL2BlockEventHandlers) == 0 { + waitNextCycle() + continue + } + + lastL2Block, err := s.GetLastL2Block(context.Background(), nil) + if errors.Is(err, ErrStateNotSynchronized) { + waitNextCycle() + continue + } else if err != nil { + log.Errorf("failed to get last l2 block while monitoring new blocks: %v", err) + waitNextCycle() + continue + } + + // not updates until now + if lastL2Block == nil || s.lastL2BlockSeen.NumberU64() >= lastL2Block.NumberU64() { + waitNextCycle() + continue + } + + for bn := s.lastL2BlockSeen.NumberU64() + uint64(1); bn <= lastL2Block.NumberU64(); bn++ { + block, err := s.GetL2BlockByNumber(context.Background(), bn, nil) + if err != nil { + log.Errorf("failed to l2 block while monitoring new blocks: %v", err) + break + } + + s.newL2BlockEvents <- NewL2BlockEvent{ + Block: *block, + } + log.Infof("new l2 blocks detected, Number %v, Hash %v", block.NumberU64(), block.Hash().String()) + s.lastL2BlockSeen = *block + } + + // interval to check for new l2 blocks + waitNextCycle() + } +} diff --git a/state/metrics/metrics.go b/state/metrics/metrics.go new file mode 100644 index 0000000000..43daf73450 --- /dev/null +++ b/state/metrics/metrics.go @@ -0,0 +1,49 @@ +package metrics + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +// CallerLabel is used to point which entity is the caller of a given function +type CallerLabel string + +const ( + // Prefix for the metrics of the state package. + Prefix = "state_" + // ExecutorProcessingTimeName is the name of the metric that shows the processing time in the executor. + ExecutorProcessingTimeName = Prefix + "executor_processing_time" + // CallerLabelName is the name of the label for the caller. + CallerLabelName = "caller" + + // SequencerCallerLabel is used when sequencer is calling the function + SequencerCallerLabel CallerLabel = "sequencer" + // SynchronizerCallerLabel is used when synchronizer is calling the function + SynchronizerCallerLabel CallerLabel = "synchronizer" + // DiscardCallerLabel is used we want to skip measuring the execution time + DiscardCallerLabel CallerLabel = "discard" +) + +// Register the metrics for the sequencer package. +func Register() { + histogramVecs := []metrics.HistogramVecOpts{ + { + HistogramOpts: prometheus.HistogramOpts{ + Name: ExecutorProcessingTimeName, + Help: "[STATE] processing time in executor", + }, + Labels: []string{CallerLabelName}, + }, + } + + metrics.RegisterHistogramVecs(histogramVecs...) +} + +// ExecutorProcessingTime observes the last processing time of the executor in the histogram vector by the provided elapsed time +// and for the given label. +func ExecutorProcessingTime(caller string, lastExecutionTime time.Duration) { + execTimeInSeconds := float64(lastExecutionTime) / float64(time.Second) + metrics.HistogramVecObserve(ExecutorProcessingTimeName, string(caller), execTimeInSeconds) +} diff --git a/state/pgstatestorage.go b/state/pgstatestorage.go index 11c65f4bb9..9389df410a 100644 --- a/state/pgstatestorage.go +++ b/state/pgstatestorage.go @@ -9,7 +9,6 @@ import ( "time" "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/proverclient/pb" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" @@ -19,74 +18,9 @@ import ( const maxTopics = 4 const ( - addGlobalExitRootSQL = "INSERT INTO state.exit_root (block_num, global_exit_root_num, mainnet_exit_root, rollup_exit_root, global_exit_root) VALUES ($1, $2, $3, $4, $5)" - getLatestExitRootSQL = "SELECT block_num, global_exit_root_num, mainnet_exit_root, rollup_exit_root, global_exit_root FROM state.exit_root ORDER BY global_exit_root_num DESC LIMIT 1" - getLatestExitRootBlockNumSQL = "SELECT block_num FROM state.exit_root ORDER BY global_exit_root_num DESC LIMIT 1" - addVirtualBatchSQL = "INSERT INTO state.virtual_batch (batch_num, tx_hash, coinbase, block_num) VALUES ($1, $2, $3, $4)" - addForcedBatchSQL = "INSERT INTO state.forced_batch (forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, batch_num, block_num) VALUES ($1, $2, $3, $4, $5, $6, $7)" - getForcedBatchSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, batch_num, block_num FROM state.forced_batch WHERE forced_batch_num = $1" - addBlockSQL = "INSERT INTO state.block (block_num, block_hash, parent_hash, received_at) VALUES ($1, $2, $3, $4)" - getLastBlockSQL = "SELECT block_num, block_hash, parent_hash, received_at FROM state.block ORDER BY block_num DESC LIMIT 1" - getPreviousBlockSQL = "SELECT block_num, block_hash, parent_hash, received_at FROM state.block ORDER BY block_num DESC LIMIT 1 OFFSET $1" - resetSQL = "DELETE FROM state.block WHERE block_num > $1" - resetTrustedStateSQL = "DELETE FROM state.batch WHERE batch_num > $1" - addVerifiedBatchSQL = "INSERT INTO state.verified_batch (block_num, batch_num, tx_hash, aggregator) VALUES ($1, $2, $3, $4)" - getVerifiedBatchSQL = "SELECT block_num, batch_num, tx_hash, aggregator FROM state.verified_batch WHERE batch_num = $1" - getLastBatchNumberSQL = "SELECT batch_num FROM state.batch ORDER BY batch_num DESC LIMIT 1" - getLastNBatchesSQL = "SELECT batch_num, global_exit_root, local_exit_root, state_root, timestamp, coinbase, raw_txs_data from state.batch ORDER BY batch_num DESC LIMIT $1" - getLastBatchTimeSQL = "SELECT timestamp FROM state.batch ORDER BY batch_num DESC LIMIT 1" - getLastVirtualBatchNumSQL = "SELECT COALESCE(MAX(batch_num), 0) FROM state.virtual_batch" - getLastVirtualBatchBlockNumSQL = "SELECT block_num FROM state.virtual_batch ORDER BY batch_num DESC LIMIT 1" - getLastBlockNumSQL = "SELECT block_num FROM state.block ORDER BY block_num DESC LIMIT 1" - getLastL2BlockNumber = "SELECT block_num FROM state.l2block ORDER BY block_num DESC LIMIT 1" - getBlockTimeByNumSQL = "SELECT received_at FROM state.block WHERE block_num = $1" - getForcedBatchByBatchNumSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, batch_num, block_num from state.forced_batch WHERE batch_num = $1" - getProcessingContextSQL = "SELECT batch_num, global_exit_root, timestamp, coinbase from state.batch WHERE batch_num = $1" - getEncodedTransactionsByBatchNumberSQL = "SELECT encoded FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num = $1" - getTransactionHashesByBatchNumberSQL = "SELECT hash FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num = $1 ORDER BY l2_block_num ASC" - getLastBatchSeenSQL = "SELECT last_batch_num_seen FROM state.sync_info LIMIT 1" - updateLastBatchSeenSQL = "UPDATE state.sync_info SET last_batch_num_seen = $1" - resetTrustedBatchSQL = "DELETE FROM state.batch WHERE batch_num > $1" - isBatchClosedSQL = "SELECT global_exit_root IS NOT NULL AND state_root IS NOT NULL FROM state.batch WHERE batch_num = $1 LIMIT 1" - addGenesisBatchSQL = `INSERT INTO state.batch (batch_num, global_exit_root, local_exit_root, state_root, timestamp, coinbase, raw_txs_data) VALUES ($1, $2, $3, $4, $5, $6, $7)` - openBatchSQL = "INSERT INTO state.batch (batch_num, global_exit_root, timestamp, coinbase) VALUES ($1, $2, $3, $4)" - closeBatchSQL = "UPDATE state.batch SET state_root = $1, local_exit_root = $2, raw_txs_data = $3 WHERE batch_num = $4" - getNextForcedBatchesSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, batch_num, block_num FROM state.forced_batch WHERE batch_num IS NULL LIMIT $1" - addBatchNumberInForcedBatchSQL = "UPDATE state.forced_batch SET batch_num = $2 WHERE forced_batch_num = $1" - getL2BlockByNumberSQL = "SELECT header, uncles, received_at FROM state.l2block b WHERE b.block_num = $1" - getL2BlockHeaderByNumberSQL = "SELECT header FROM state.l2block b WHERE b.block_num = $1" - getTransactionByHashSQL = "SELECT transaction.encoded FROM state.transaction WHERE hash = $1" - getTransactionByL2BlockHashAndIndexSQL = "SELECT t.encoded FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.batch_num WHERE b.block_hash = $1 AND 0 = $2" - getTransactionByL2BlockNumberAndIndexSQL = "SELECT t.encoded FROM state.transaction t WHERE t.l2_block_num = $1 AND 0 = $2" - getL2BlockTransactionCountByHashSQL = "SELECT COUNT(*) FROM state.transaction t INNER JOIN state.l2block b ON b.block_num = t.l2_block_num WHERE b.block_hash = $1" - getL2BlockTransactionCountByNumberSQL = "SELECT COUNT(*) FROM state.transaction t WHERE t.l2_block_num = $1" - getLastConsolidatedBlockNumberSQL = "SELECT b.block_num FROM state.l2block b INNER JOIN state.verified_batch vb ON vb.batch_num = b.batch_num ORDER BY b.block_num DESC LIMIT 1" - getLastVirtualBlockHeaderSQL = "SELECT b.header FROM state.l2block b INNER JOIN state.virtual_batch vb ON vb.batch_num = b.batch_num ORDER BY b.block_num DESC LIMIT 1" - getL2BlockByHashSQL = "SELECT header, uncles, received_at FROM state.l2block b WHERE b.block_hash = $1" - getLastL2BlockSQL = "SELECT header, uncles, received_at FROM state.l2block b ORDER BY b.block_num DESC LIMIT 1" - getL2BlockHeaderByHashSQL = "SELECT header FROM state.l2block b WHERE b.block_hash = $1" - getTxsByBlockNumSQL = "SELECT encoded FROM state.transaction WHERE l2_block_num = $1" - getL2BlockHashesSinceSQL = "SELECT block_hash FROM state.l2block WHERE received_at >= $1" - getSyncingInfoSQL = ` - SELECT coalesce(MIN(initial_blocks.block_num), 0) as init_sync_block - , coalesce(MAX(virtual_blocks.block_num), 0) as last_block_num_seen - , coalesce(MAX(consolidated_blocks.block_num), 0) as last_block_num_consolidated - , coalesce(MIN(sy.init_sync_batch), 0) as init_sync_batch - , coalesce(MIN(sy.last_batch_num_seen), 0) as last_batch_num_seen - , coalesce(MIN(sy.last_batch_num_consolidated), 0) as last_batch_num_consolidated - FROM state.sync_info sy - INNER JOIN state.l2block initial_blocks - ON initial_blocks.batch_num = sy.init_sync_batch - INNER JOIN state.l2block virtual_blocks - ON virtual_blocks.batch_num = sy.last_batch_num_seen - INNER JOIN state.l2block consolidated_blocks - ON consolidated_blocks.batch_num = sy.last_batch_num_consolidated; - ` - addTransactionSQL = "INSERT INTO state.transaction (hash, encoded, decoded, l2_block_num) VALUES($1, $2, $3, $4)" - getBatchNumByBlockNum = "SELECT batch_num FROM state.virtual_batch WHERE block_num = $1 ORDER BY batch_num ASC LIMIT 1" - getTxsHashesBeforeBatchNum = "SELECT hash FROM state.transaction JOIN state.l2block ON state.transaction.l2_block_num = state.l2block.block_num AND state.l2block.batch_num <= $1" - isL2BlockVirtualized = "SELECT l2b.block_num FROM state.l2block l2b INNER JOIN state.virtual_batch vb ON vb.batch_num = l2b.batch_num WHERE l2b.block_num = $1" - isL2BlockConsolidated = "SELECT l2b.block_num FROM state.l2block l2b INNER JOIN state.verified_batch vb ON vb.batch_num = l2b.batch_num WHERE l2b.block_num = $1" + getLastBatchNumberSQL = "SELECT batch_num FROM state.batch ORDER BY batch_num DESC LIMIT 1" + getLastBlockNumSQL = "SELECT block_num FROM state.block ORDER BY block_num DESC LIMIT 1" + getBlockTimeByNumSQL = "SELECT received_at FROM state.block WHERE block_num = $1" ) // PostgresStorage implements the Storage interface @@ -112,26 +46,58 @@ func (p *PostgresStorage) getExecQuerier(dbTx pgx.Tx) execQuerier { // Reset resets the state to a block for the given DB tx func (p *PostgresStorage) Reset(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) error { e := p.getExecQuerier(dbTx) + const resetSQL = "DELETE FROM state.block WHERE block_num > $1" if _, err := e.Exec(ctx, resetSQL, blockNumber); err != nil { return err } - // TODO: Remove consolidations + + return nil +} + +// ResetForkID resets the state to reprocess the newer batches with the correct forkID +func (p *PostgresStorage) ResetForkID(ctx context.Context, batchNumber, forkID uint64, version string, dbTx pgx.Tx) error { + e := p.getExecQuerier(dbTx) + const resetVirtualStateSQL = "delete from state.block where block_num >=(select min(block_num) from state.virtual_batch where batch_num >= $1)" + if _, err := e.Exec(ctx, resetVirtualStateSQL, batchNumber); err != nil { + return err + } + err := p.ResetTrustedState(ctx, batchNumber-1, dbTx) + if err != nil { + return err + } + reorg := TrustedReorg{ + BatchNumber: batchNumber, + Reason: fmt.Sprintf("New ForkID: %d. Version: %s", forkID, version), + } + err = p.AddTrustedReorg(ctx, &reorg, dbTx) + if err != nil { + return err + } + + // Delete proofs for higher batches + const deleteProofsSQL = "delete from state.proof where batch_num >= $1 or (batch_num <= $1 and batch_num_final >= $1)" + if _, err := e.Exec(ctx, deleteProofsSQL, batchNumber); err != nil { + return err + } + return nil } // ResetTrustedState removes the batches with number greater than the given one // from the database. -func (p *PostgresStorage) ResetTrustedState(ctx context.Context, batchNum uint64, dbTx pgx.Tx) error { +func (p *PostgresStorage) ResetTrustedState(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { + const resetTrustedStateSQL = "DELETE FROM state.batch WHERE batch_num > $1" e := p.getExecQuerier(dbTx) - if _, err := e.Exec(ctx, resetTrustedStateSQL, batchNum); err != nil { + if _, err := e.Exec(ctx, resetTrustedStateSQL, batchNumber); err != nil { return err } - // TODO: Remove consolidations return nil } // AddBlock adds a new block to the State Store func (p *PostgresStorage) AddBlock(ctx context.Context, block *Block, dbTx pgx.Tx) error { + const addBlockSQL = "INSERT INTO state.block (block_num, block_hash, parent_hash, received_at) VALUES ($1, $2, $3, $4)" + e := p.getExecQuerier(dbTx) _, err := e.Exec(ctx, addBlockSQL, block.BlockNumber, block.BlockHash.String(), block.ParentHash.String(), block.ReceivedAt) return err @@ -140,6 +106,9 @@ func (p *PostgresStorage) AddBlock(ctx context.Context, block *Block, dbTx pgx.T // GetTxsOlderThanNL1Blocks get txs hashes to delete from tx pool func (p *PostgresStorage) GetTxsOlderThanNL1Blocks(ctx context.Context, nL1Blocks uint64, dbTx pgx.Tx) ([]common.Hash, error) { var batchNum, blockNum uint64 + const getBatchNumByBlockNumFromVirtualBatch = "SELECT batch_num FROM state.virtual_batch WHERE block_num <= $1 ORDER BY batch_num DESC LIMIT 1" + const getTxsHashesBeforeBatchNum = "SELECT hash FROM state.transaction JOIN state.l2block ON state.transaction.l2_block_num = state.l2block.block_num AND state.l2block.batch_num <= $1" + e := p.getExecQuerier(dbTx) err := e.QueryRow(ctx, getLastBlockNumSQL).Scan(&blockNum) @@ -154,13 +123,12 @@ func (p *PostgresStorage) GetTxsOlderThanNL1Blocks(ctx context.Context, nL1Block return nil, errors.New("blockNumDiff is too big, there are no txs to delete") } - err = e.QueryRow(ctx, getBatchNumByBlockNum, blockNum).Scan(&batchNum) + err = e.QueryRow(ctx, getBatchNumByBlockNumFromVirtualBatch, blockNum).Scan(&batchNum) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { return nil, err } - rows, err := e.Query(ctx, getTxsHashesBeforeBatchNum, batchNum) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound @@ -187,6 +155,8 @@ func (p *PostgresStorage) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*Block parentHash string block Block ) + const getLastBlockSQL = "SELECT block_num, block_hash, parent_hash, received_at FROM state.block ORDER BY block_num DESC LIMIT 1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getLastBlockSQL).Scan(&block.BlockNumber, &blockHash, &parentHash, &block.ReceivedAt) @@ -205,6 +175,8 @@ func (p *PostgresStorage) GetPreviousBlock(ctx context.Context, offset uint64, d parentHash string block Block ) + const getPreviousBlockSQL = "SELECT block_num, block_hash, parent_hash, received_at FROM state.block ORDER BY block_num DESC LIMIT 1 OFFSET $1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getPreviousBlockSQL, offset).Scan(&block.BlockNumber, &blockHash, &parentHash, &block.ReceivedAt) @@ -218,29 +190,39 @@ func (p *PostgresStorage) GetPreviousBlock(ctx context.Context, offset uint64, d // AddGlobalExitRoot adds a new ExitRoot to the db func (p *PostgresStorage) AddGlobalExitRoot(ctx context.Context, exitRoot *GlobalExitRoot, dbTx pgx.Tx) error { + const addGlobalExitRootSQL = "INSERT INTO state.exit_root (block_num, timestamp, mainnet_exit_root, rollup_exit_root, global_exit_root) VALUES ($1, $2, $3, $4, $5)" + e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addGlobalExitRootSQL, exitRoot.BlockNumber, exitRoot.GlobalExitRootNum.String(), exitRoot.MainnetExitRoot, exitRoot.RollupExitRoot, exitRoot.GlobalExitRoot) + _, err := e.Exec(ctx, addGlobalExitRootSQL, exitRoot.BlockNumber, exitRoot.Timestamp, exitRoot.MainnetExitRoot, exitRoot.RollupExitRoot, exitRoot.GlobalExitRoot) return err } // GetLatestGlobalExitRoot get the latest global ExitRoot synced. -func (p *PostgresStorage) GetLatestGlobalExitRoot(ctx context.Context, dbTx pgx.Tx) (*GlobalExitRoot, error) { +func (p *PostgresStorage) GetLatestGlobalExitRoot(ctx context.Context, maxBlockNumber uint64, dbTx pgx.Tx) (GlobalExitRoot, time.Time, error) { + const getLatestExitRootSQL = "SELECT block_num, mainnet_exit_root, rollup_exit_root, global_exit_root FROM state.exit_root WHERE block_num <= $1 ORDER BY id DESC LIMIT 1" + var ( - exitRoot GlobalExitRoot - globalNum uint64 - err error + exitRoot GlobalExitRoot + err error + receivedAt time.Time ) e := p.getExecQuerier(dbTx) - err = e.QueryRow(ctx, getLatestExitRootSQL).Scan(&exitRoot.BlockNumber, &globalNum, &exitRoot.MainnetExitRoot, &exitRoot.RollupExitRoot, &exitRoot.GlobalExitRoot) + err = e.QueryRow(ctx, getLatestExitRootSQL, maxBlockNumber).Scan(&exitRoot.BlockNumber, &exitRoot.MainnetExitRoot, &exitRoot.RollupExitRoot, &exitRoot.GlobalExitRoot) if errors.Is(err, pgx.ErrNoRows) { - return nil, ErrNotFound + return GlobalExitRoot{}, time.Time{}, ErrNotFound } else if err != nil { - return nil, err + return GlobalExitRoot{}, time.Time{}, err } - exitRoot.GlobalExitRootNum = new(big.Int).SetUint64(globalNum) - return &exitRoot, nil + + err = e.QueryRow(ctx, getBlockTimeByNumSQL, exitRoot.BlockNumber).Scan(&receivedAt) + if errors.Is(err, pgx.ErrNoRows) { + return GlobalExitRoot{}, time.Time{}, ErrNotFound + } else if err != nil { + return GlobalExitRoot{}, time.Time{}, err + } + return exitRoot, receivedAt, nil } // GetNumberOfBlocksSinceLastGERUpdate gets number of blocks since last global exit root update @@ -250,6 +232,8 @@ func (p *PostgresStorage) GetNumberOfBlocksSinceLastGERUpdate(ctx context.Contex lastExitRootBlockNum uint64 err error ) + const getLatestExitRootBlockNumSQL = "SELECT block_num FROM state.exit_root ORDER BY id DESC LIMIT 1" + e := p.getExecQuerier(dbTx) err = e.QueryRow(ctx, getLastBlockNumSQL).Scan(&lastBlockNum) if errors.Is(err, pgx.ErrNoRows) { @@ -274,9 +258,10 @@ func (p *PostgresStorage) GetBlockNumAndMainnetExitRootByGER(ctx context.Context blockNum uint64 mainnetExitRoot common.Hash ) - e := p.getExecQuerier(dbTx) const getMainnetExitRoot = "SELECT block_num, mainnet_exit_root FROM state.exit_root WHERE global_exit_root = $1" - err := e.QueryRow(ctx, getMainnetExitRoot, ger.String()).Scan(&blockNum, &mainnetExitRoot) + + e := p.getExecQuerier(dbTx) + err := e.QueryRow(ctx, getMainnetExitRoot, ger.Bytes()).Scan(&blockNum, &mainnetExitRoot) if errors.Is(err, pgx.ErrNoRows) { return 0, common.Hash{}, ErrNotFound } else if err != nil { @@ -293,6 +278,8 @@ func (p *PostgresStorage) GetTimeForLatestBatchVirtualization(ctx context.Contex blockNum uint64 timestamp time.Time ) + const getLastVirtualBatchBlockNumSQL = "SELECT block_num FROM state.virtual_batch ORDER BY batch_num DESC LIMIT 1" + e := p.getExecQuerier(dbTx) err := e.QueryRow(ctx, getLastVirtualBatchBlockNumSQL).Scan(&blockNum) @@ -315,7 +302,8 @@ func (p *PostgresStorage) GetTimeForLatestBatchVirtualization(ctx context.Contex // AddForcedBatch adds a new ForcedBatch to the db func (p *PostgresStorage) AddForcedBatch(ctx context.Context, forcedBatch *ForcedBatch, tx pgx.Tx) error { - _, err := tx.Exec(ctx, addForcedBatchSQL, forcedBatch.ForcedBatchNumber, forcedBatch.GlobalExitRoot.String(), forcedBatch.ForcedAt, forcedBatch.RawTxsData, forcedBatch.Sequencer.String(), forcedBatch.BatchNumber, forcedBatch.BlockNumber) + const addForcedBatchSQL = "INSERT INTO state.forced_batch (forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, block_num) VALUES ($1, $2, $3, $4, $5, $6)" + _, err := tx.Exec(ctx, addForcedBatchSQL, forcedBatch.ForcedBatchNumber, forcedBatch.GlobalExitRoot.String(), forcedBatch.ForcedAt, hex.EncodeToString(forcedBatch.RawTxsData), forcedBatch.Sequencer.String(), forcedBatch.BlockNumber) return err } @@ -327,8 +315,9 @@ func (p *PostgresStorage) GetForcedBatch(ctx context.Context, forcedBatchNumber rawTxs string seq string ) + const getForcedBatchSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, block_num FROM state.forced_batch WHERE forced_batch_num = $1" e := p.getExecQuerier(dbTx) - err := e.QueryRow(ctx, getForcedBatchSQL, forcedBatchNumber).Scan(&forcedBatch.ForcedBatchNumber, &globalExitRoot, &forcedBatch.ForcedAt, &rawTxs, &seq, &forcedBatch.BatchNumber, &forcedBatch.BlockNumber) + err := e.QueryRow(ctx, getForcedBatchSQL, forcedBatchNumber).Scan(&forcedBatch.ForcedBatchNumber, &globalExitRoot, &forcedBatch.ForcedAt, &rawTxs, &seq, &forcedBatch.BlockNumber) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { @@ -343,34 +332,37 @@ func (p *PostgresStorage) GetForcedBatch(ctx context.Context, forcedBatchNumber return &forcedBatch, nil } -// GetForcedBatchByBatchNumber gets an L1 forcedBatch by batch number. -func (p *PostgresStorage) GetForcedBatchByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*ForcedBatch, error) { - var ( - forcedBatch ForcedBatch - globalExitRoot string - rawTxs string - seq string - ) - e := p.getExecQuerier(dbTx) - err := e.QueryRow(ctx, getForcedBatchByBatchNumSQL, batchNumber).Scan(&forcedBatch.ForcedBatchNumber, &globalExitRoot, &forcedBatch.ForcedAt, &rawTxs, &seq, &forcedBatch.BatchNumber, &forcedBatch.BlockNumber) +// GetForcedBatchesSince gets L1 forced batches since forcedBatchNumber +func (p *PostgresStorage) GetForcedBatchesSince(ctx context.Context, forcedBatchNumber, maxBlockNumber uint64, dbTx pgx.Tx) ([]*ForcedBatch, error) { + const getForcedBatchesSQL = "SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, block_num FROM state.forced_batch WHERE forced_batch_num > $1 AND block_num <= $2 ORDER BY forced_batch_num ASC" + q := p.getExecQuerier(dbTx) + rows, err := q.Query(ctx, getForcedBatchesSQL, forcedBatchNumber, maxBlockNumber) if errors.Is(err, pgx.ErrNoRows) { - return nil, ErrNotFound + return []*ForcedBatch{}, nil } else if err != nil { return nil, err } - forcedBatch.RawTxsData, err = hex.DecodeString(rawTxs) - if err != nil { - return nil, err + defer rows.Close() + + forcesBatches := make([]*ForcedBatch, 0, len(rows.RawValues())) + + for rows.Next() { + forcedBatch, err := scanForcedBatch(rows) + if err != nil { + return nil, err + } + + forcesBatches = append(forcesBatches, &forcedBatch) } - forcedBatch.Sequencer = common.HexToAddress(seq) - forcedBatch.GlobalExitRoot = common.HexToHash(globalExitRoot) - return &forcedBatch, nil + + return forcesBatches, nil } // AddVerifiedBatch adds a new VerifiedBatch to the db func (p *PostgresStorage) AddVerifiedBatch(ctx context.Context, verifiedBatch *VerifiedBatch, dbTx pgx.Tx) error { e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addVerifiedBatchSQL, verifiedBatch.BlockNumber, verifiedBatch.BatchNumber, verifiedBatch.TxHash.String(), verifiedBatch.Aggregator.String()) + const addVerifiedBatchSQL = "INSERT INTO state.verified_batch (block_num, batch_num, tx_hash, aggregator, state_root, is_trusted) VALUES ($1, $2, $3, $4, $5, $6)" + _, err := e.Exec(ctx, addVerifiedBatchSQL, verifiedBatch.BlockNumber, verifiedBatch.BatchNumber, verifiedBatch.TxHash.String(), verifiedBatch.Aggregator.String(), verifiedBatch.StateRoot.String(), verifiedBatch.IsTrusted) return err } @@ -380,9 +372,16 @@ func (p *PostgresStorage) GetVerifiedBatch(ctx context.Context, batchNumber uint verifiedBatch VerifiedBatch txHash string agg string + sr string ) + + const getVerifiedBatchSQL = ` + SELECT block_num, batch_num, tx_hash, aggregator, state_root, is_trusted + FROM state.verified_batch + WHERE batch_num = $1` + e := p.getExecQuerier(dbTx) - err := e.QueryRow(ctx, getVerifiedBatchSQL, batchNumber).Scan(&verifiedBatch.BlockNumber, &verifiedBatch.BatchNumber, &txHash, &agg) + err := e.QueryRow(ctx, getVerifiedBatchSQL, batchNumber).Scan(&verifiedBatch.BlockNumber, &verifiedBatch.BatchNumber, &txHash, &agg, &sr, &verifiedBatch.IsTrusted) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { @@ -390,11 +389,14 @@ func (p *PostgresStorage) GetVerifiedBatch(ctx context.Context, batchNumber uint } verifiedBatch.Aggregator = common.HexToAddress(agg) verifiedBatch.TxHash = common.HexToHash(txHash) + verifiedBatch.StateRoot = common.HexToHash(sr) return &verifiedBatch, nil } // GetLastNBatches returns the last numBatches batches. func (p *PostgresStorage) GetLastNBatches(ctx context.Context, numBatches uint, dbTx pgx.Tx) ([]*Batch, error) { + const getLastNBatchesSQL = "SELECT batch_num, global_exit_root, local_exit_root, acc_input_hash, state_root, timestamp, coinbase, raw_txs_data, forced_batch_num from state.batch ORDER BY batch_num DESC LIMIT $1" + e := p.getExecQuerier(dbTx) rows, err := e.Query(ctx, getLastNBatchesSQL, numBatches) if errors.Is(err, pgx.ErrNoRows) { @@ -424,6 +426,7 @@ func (p *PostgresStorage) GetLastNBatchesByL2BlockNumber(ctx context.Context, l2 SELECT b.batch_num, b.global_exit_root, b.local_exit_root, + b.acc_input_hash, b.state_root, b.timestamp, b.coinbase, @@ -442,7 +445,7 @@ func (p *PostgresStorage) GetLastNBatchesByL2BlockNumber(ctx context.Context, l2 WHERE l2b.block_num = $1)) /* OR if $1 is null, this means we want to get the most updated information from state, so it considers all the batches. * this is generally used by estimate gas, process unsigned transactions and it is required by claim transactions to add - * the open batch to the result and get the most updated GER synced from L1 and stored in the current open batch when + * the open batch to the result and get the most updated globalExitRoot synced from L1 and stored in the current open batch when * there was not transactions yet to create a l2 block with it */ OR $1 IS NULL ORDER BY b.batch_num DESC @@ -459,6 +462,7 @@ func (p *PostgresStorage) GetLastNBatchesByL2BlockNumber(ctx context.Context, l2 defer rows.Close() batches := make([]*Batch, 0, len(rows.RawValues())) + emptyHash := common.Hash{} for rows.Next() { batch, _l2BlockStateRoot, err := scanBatchWithL2BlockStateRoot(rows) @@ -469,6 +473,11 @@ func (p *PostgresStorage) GetLastNBatchesByL2BlockNumber(ctx context.Context, l2 if l2BlockStateRoot == nil && _l2BlockStateRoot != nil { l2BlockStateRoot = _l2BlockStateRoot } + // if there is no corresponding l2_block, it will use the latest batch state_root + // it is related to https://github.com/0xPolygonHermez/zkevm-node/issues/1299 + if l2BlockStateRoot == nil && batch.StateRoot != emptyHash { + l2BlockStateRoot = &batch.StateRoot + } } return batches, *l2BlockStateRoot, nil @@ -489,6 +498,8 @@ func (p *PostgresStorage) GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) ( // GetLastBatchTime gets last trusted batch time func (p *PostgresStorage) GetLastBatchTime(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { var timestamp time.Time + const getLastBatchTimeSQL = "SELECT timestamp FROM state.batch ORDER BY batch_num DESC LIMIT 1" + e := p.getExecQuerier(dbTx) err := e.QueryRow(ctx, getLastBatchTimeSQL).Scan(×tamp) @@ -503,6 +514,8 @@ func (p *PostgresStorage) GetLastBatchTime(ctx context.Context, dbTx pgx.Tx) (ti // GetLastVirtualBatchNum gets last virtual batch num func (p *PostgresStorage) GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { var batchNum uint64 + const getLastVirtualBatchNumSQL = "SELECT COALESCE(MAX(batch_num), 0) FROM state.virtual_batch" + e := p.getExecQuerier(dbTx) err := e.QueryRow(ctx, getLastVirtualBatchNumSQL).Scan(&batchNum) @@ -514,34 +527,48 @@ func (p *PostgresStorage) GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.T return batchNum, nil } -// SetLastBatchNumberSeenOnEthereum sets the last batch number that affected -// the roll-up in order to allow the components to know if the state -// is synchronized or not -func (p *PostgresStorage) SetLastBatchNumberSeenOnEthereum(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { +// GetLatestVirtualBatchTimestamp gets last virtual batch timestamp +func (p *PostgresStorage) GetLatestVirtualBatchTimestamp(ctx context.Context, dbTx pgx.Tx) (time.Time, error) { + const getLastVirtualBatchTimestampSQL = `SELECT COALESCE(MAX(block.received_at), NOW()) FROM state.virtual_batch INNER JOIN state.block ON state.block.block_num = virtual_batch.block_num` + var timestamp time.Time e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, updateLastBatchSeenSQL, batchNumber) - return err + err := e.QueryRow(ctx, getLastVirtualBatchTimestampSQL).Scan(×tamp) + + if errors.Is(err, pgx.ErrNoRows) { + return time.Unix(0, 0), ErrNotFound + } else if err != nil { + return time.Unix(0, 0), err + } + return timestamp, nil } -// GetLastBatchNumberSeenOnEthereum returns the last batch number stored -// in the state that represents the last batch number that affected the -// roll-up in the Ethereum network. -func (p *PostgresStorage) GetLastBatchNumberSeenOnEthereum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { - var batchNumber uint64 +// SetLastBatchInfoSeenOnEthereum sets the last batch number that affected +// the roll-up and the last batch number that was consolidated on ethereum +// in order to allow the components to know if the state is synchronized or not +func (p *PostgresStorage) SetLastBatchInfoSeenOnEthereum(ctx context.Context, lastBatchNumberSeen, lastBatchNumberVerified uint64, dbTx pgx.Tx) error { + const query = ` + UPDATE state.sync_info + SET last_batch_num_seen = $1 + , last_batch_num_consolidated = $2` + e := p.getExecQuerier(dbTx) - err := e.QueryRow(ctx, getLastBatchSeenSQL).Scan(&batchNumber) + _, err := e.Exec(ctx, query, lastBatchNumberSeen, lastBatchNumberVerified) + return err +} - if err != nil { - return 0, err - } +// SetInitSyncBatch sets the initial batch number where the synchronization started +func (p *PostgresStorage) SetInitSyncBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { + updateInitBatchSQL := "UPDATE state.sync_info SET init_sync_batch = $1" - return batchNumber, nil + e := p.getExecQuerier(dbTx) + _, err := e.Exec(ctx, updateInitBatchSQL, batchNumber) + return err } // GetBatchByNumber returns the batch with the given number. func (p *PostgresStorage) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*Batch, error) { const getBatchByNumberSQL = ` - SELECT batch_num, global_exit_root, local_exit_root, state_root, timestamp, coinbase, raw_txs_data + SELECT batch_num, global_exit_root, local_exit_root, acc_input_hash, state_root, timestamp, coinbase, raw_txs_data, forced_batch_num FROM state.batch WHERE batch_num = $1` @@ -554,13 +581,14 @@ func (p *PostgresStorage) GetBatchByNumber(ctx context.Context, batchNumber uint } else if err != nil { return nil, err } + return &batch, nil } // GetBatchByTxHash returns the batch including the given tx func (p *PostgresStorage) GetBatchByTxHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*Batch, error) { const getBatchByTxHashSQL = ` - SELECT b.batch_num, b.global_exit_root, b.local_exit_root, b.state_root, b.timestamp, b.coinbase, b.raw_txs_data + SELECT b.batch_num, b.global_exit_root, b.local_exit_root, b.acc_input_hash, b.state_root, b.timestamp, b.coinbase, b.raw_txs_data, b.forced_batch_num FROM state.transaction t, state.batch b, state.l2block l WHERE t.hash = $1 AND l.block_num = t.l2_block_num AND b.batch_num = l.batch_num` @@ -579,7 +607,7 @@ func (p *PostgresStorage) GetBatchByTxHash(ctx context.Context, transactionHash // GetBatchByL2BlockNumber returns the batch related to the l2 block accordingly to the provided l2 block number. func (p *PostgresStorage) GetBatchByL2BlockNumber(ctx context.Context, l2BlockNumber uint64, dbTx pgx.Tx) (*Batch, error) { const getBatchByL2BlockNumberSQL = ` - SELECT bt.batch_num, bt.global_exit_root, bt.local_exit_root, bt.state_root, bt.timestamp, bt.coinbase, bt.raw_txs_data + SELECT bt.batch_num, bt.global_exit_root, bt.local_exit_root, bt.acc_input_hash, bt.state_root, bt.timestamp, bt.coinbase, bt.raw_txs_data, bt.forced_batch_num FROM state.batch bt INNER JOIN state.l2block bl ON bt.batch_num = bl.batch_num @@ -605,10 +633,12 @@ func (p *PostgresStorage) GetVirtualBatchByNumber(ctx context.Context, batchNumb batch_num, global_exit_root, local_exit_root, + acc_input_hash, state_root, timestamp, coinbase, - raw_txs_data + raw_txs_data, + forced_batch_num FROM state.batch WHERE @@ -639,8 +669,34 @@ func (p *PostgresStorage) IsBatchVirtualized(ctx context.Context, batchNumber ui return exists, nil } +// IsBatchConsolidated checks if batch is consolidated/verified. +func (p *PostgresStorage) IsBatchConsolidated(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (bool, error) { + const query = `SELECT EXISTS (SELECT 1 FROM state.verified_batch WHERE batch_num = $1)` + e := p.getExecQuerier(dbTx) + var exists bool + err := e.QueryRow(ctx, query, batchNumber).Scan(&exists) + if err != nil && !errors.Is(err, pgx.ErrNoRows) { + return exists, err + } + return exists, nil +} + +// IsSequencingTXSynced checks if sequencing tx has been synced into the state +func (p *PostgresStorage) IsSequencingTXSynced(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (bool, error) { + const query = `SELECT EXISTS (SELECT 1 FROM state.virtual_batch WHERE tx_hash = $1)` + e := p.getExecQuerier(dbTx) + var exists bool + err := e.QueryRow(ctx, query, transactionHash.String()).Scan(&exists) + if err != nil && !errors.Is(err, pgx.ErrNoRows) { + return exists, err + } + return exists, nil +} + // GetProcessingContext returns the processing context for the given batch. func (p *PostgresStorage) GetProcessingContext(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*ProcessingContext, error) { + const getProcessingContextSQL = "SELECT batch_num, global_exit_root, timestamp, coinbase, forced_batch_num from state.batch WHERE batch_num = $1" + e := p.getExecQuerier(dbTx) row := e.QueryRow(ctx, getProcessingContextSQL, batchNumber) processingContext := ProcessingContext{} @@ -653,6 +709,7 @@ func (p *PostgresStorage) GetProcessingContext(ctx context.Context, batchNumber &gerStr, &processingContext.Timestamp, &coinbaseStr, + &processingContext.ForcedBatchNum, ); errors.Is(err, pgx.ErrNoRows) { return nil, ErrStateNotSynchronized } else if err != nil { @@ -669,6 +726,7 @@ func scanBatch(row pgx.Row) (Batch, error) { var ( gerStr string lerStr *string + aihStr *string stateStr *string coinbaseStr string ) @@ -676,10 +734,12 @@ func scanBatch(row pgx.Row) (Batch, error) { &batch.BatchNumber, &gerStr, &lerStr, + &aihStr, &stateStr, &batch.Timestamp, &coinbaseStr, &batch.BatchL2Data, + &batch.ForcedBatchNum, ); err != nil { return batch, err } @@ -690,6 +750,9 @@ func scanBatch(row pgx.Row) (Batch, error) { if stateStr != nil { batch.StateRoot = common.HexToHash(*stateStr) } + if aihStr != nil { + batch.AccInputHash = common.HexToHash(*aihStr) + } batch.Coinbase = common.HexToAddress(coinbaseStr) return batch, nil @@ -700,6 +763,7 @@ func scanBatchWithL2BlockStateRoot(row pgx.Row) (Batch, *common.Hash, error) { var ( gerStr string lerStr *string + aihStr *string stateStr *string coinbaseStr string l2BlockStateRootStr *string @@ -708,6 +772,7 @@ func scanBatchWithL2BlockStateRoot(row pgx.Row) (Batch, *common.Hash, error) { &batch.BatchNumber, &gerStr, &lerStr, + &aihStr, &stateStr, &batch.Timestamp, &coinbaseStr, @@ -723,6 +788,9 @@ func scanBatchWithL2BlockStateRoot(row pgx.Row) (Batch, *common.Hash, error) { if stateStr != nil { batch.StateRoot = common.HexToHash(*stateStr) } + if stateStr != nil { + batch.AccInputHash = common.HexToHash(*aihStr) + } var l2BlockStateRoot *common.Hash if l2BlockStateRootStr != nil { h := common.HexToHash(*l2BlockStateRootStr) @@ -733,9 +801,32 @@ func scanBatchWithL2BlockStateRoot(row pgx.Row) (Batch, *common.Hash, error) { return batch, l2BlockStateRoot, nil } +func scanForcedBatch(row pgx.Row) (ForcedBatch, error) { + forcedBatch := ForcedBatch{} + var ( + gerStr string + coinbaseStr string + ) + if err := row.Scan( + &forcedBatch.ForcedBatchNumber, + &gerStr, + &forcedBatch.ForcedAt, + &forcedBatch.RawTxsData, + &coinbaseStr, + &forcedBatch.BlockNumber, + ); err != nil { + return forcedBatch, err + } + forcedBatch.GlobalExitRoot = common.HexToHash(gerStr) + forcedBatch.Sequencer = common.HexToAddress(coinbaseStr) + return forcedBatch, nil +} + // GetEncodedTransactionsByBatchNumber returns the encoded field of all // transactions in the given batch. func (p *PostgresStorage) GetEncodedTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (encoded []string, err error) { + const getEncodedTransactionsByBatchNumberSQL = "SELECT encoded FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num = $1 ORDER BY l2_block_num ASC" + e := p.getExecQuerier(dbTx) rows, err := e.Query(ctx, getEncodedTransactionsByBatchNumberSQL, batchNumber) if !errors.Is(err, pgx.ErrNoRows) && err != nil { @@ -776,6 +867,8 @@ func (p *PostgresStorage) GetTransactionsByBatchNumber(ctx context.Context, batc // GetTxsHashesByBatchNumber returns the hashes of the transactions in the // given batch. func (p *PostgresStorage) GetTxsHashesByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (encoded []common.Hash, err error) { + const getTransactionHashesByBatchNumberSQL = "SELECT hash FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num = $1 ORDER BY l2_block_num ASC" + e := p.getExecQuerier(dbTx) rows, err := e.Query(ctx, getTransactionHashesByBatchNumberSQL, batchNumber) if !errors.Is(err, pgx.ErrNoRows) && err != nil { @@ -797,23 +890,46 @@ func (p *PostgresStorage) GetTxsHashesByBatchNumber(ctx context.Context, batchNu return txs, nil } -// ResetTrustedBatch resets the batches which the batch number is higher than the input. -func (p *PostgresStorage) ResetTrustedBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { +// AddVirtualBatch adds a new virtual batch to the storage. +func (p *PostgresStorage) AddVirtualBatch(ctx context.Context, virtualBatch *VirtualBatch, dbTx pgx.Tx) error { + const addVirtualBatchSQL = "INSERT INTO state.virtual_batch (batch_num, tx_hash, coinbase, block_num, sequencer_addr) VALUES ($1, $2, $3, $4, $5)" e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, resetTrustedBatchSQL, batchNumber) + _, err := e.Exec(ctx, addVirtualBatchSQL, virtualBatch.BatchNumber, virtualBatch.TxHash.String(), virtualBatch.Coinbase.String(), virtualBatch.BlockNumber, virtualBatch.SequencerAddr.String()) return err } -// AddVirtualBatch adds a new virtual batch to the storage. -func (p *PostgresStorage) AddVirtualBatch(ctx context.Context, virtualBatch *VirtualBatch, dbTx pgx.Tx) error { +// GetVirtualBatch get an L1 virtualBatch. +func (p *PostgresStorage) GetVirtualBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*VirtualBatch, error) { + var ( + virtualBatch VirtualBatch + txHash string + coinbase string + sequencerAddr string + ) + + const getVirtualBatchSQL = ` + SELECT block_num, batch_num, tx_hash, coinbase, sequencer_addr + FROM state.virtual_batch + WHERE batch_num = $1` + e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addVirtualBatchSQL, virtualBatch.BatchNumber, virtualBatch.TxHash.String(), virtualBatch.Coinbase.String(), virtualBatch.BlockNumber) - return err + err := e.QueryRow(ctx, getVirtualBatchSQL, batchNumber).Scan(&virtualBatch.BlockNumber, &virtualBatch.BatchNumber, &txHash, &coinbase, &sequencerAddr) + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrNotFound + } else if err != nil { + return nil, err + } + virtualBatch.Coinbase = common.HexToAddress(coinbase) + virtualBatch.SequencerAddr = common.HexToAddress(sequencerAddr) + virtualBatch.TxHash = common.HexToHash(txHash) + return &virtualBatch, nil } func (p *PostgresStorage) storeGenesisBatch(ctx context.Context, batch Batch, dbTx pgx.Tx) error { + const addGenesisBatchSQL = "INSERT INTO state.batch (batch_num, global_exit_root, local_exit_root, acc_input_hash, state_root, timestamp, coinbase, raw_txs_data, forced_batch_num) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)" + if batch.BatchNumber != 0 { - return fmt.Errorf("unexpected batch number. Got %d, should be 0", batch.BatchNumber) + return fmt.Errorf("%w. Got %d, should be 0", ErrUnexpectedBatch, batch.BatchNumber) } e := p.getExecQuerier(dbTx) _, err := e.Exec( @@ -822,20 +938,24 @@ func (p *PostgresStorage) storeGenesisBatch(ctx context.Context, batch Batch, db batch.BatchNumber, batch.GlobalExitRoot.String(), batch.LocalExitRoot.String(), + batch.AccInputHash.String(), batch.StateRoot.String(), batch.Timestamp.UTC(), batch.Coinbase.String(), batch.BatchL2Data, + batch.ForcedBatchNum, ) return err } // openBatch adds a new batch into the state, with the necessary data to start processing transactions within it. -// It's meant to be used by sequencers, since they don't necessarely know what transactions are going to be added +// It's meant to be used by sequencers, since they don't necessarily know what transactions are going to be added // in this batch yet. In other words it's the creation of a WIP batch. -// Note that this will add a batch with batch number N + 1, where N it's the greates batch number on the state. +// Note that this will add a batch with batch number N + 1, where N it's the greatest batch number on the state. func (p *PostgresStorage) openBatch(ctx context.Context, batchContext ProcessingContext, dbTx pgx.Tx) error { + const openBatchSQL = "INSERT INTO state.batch (batch_num, global_exit_root, timestamp, coinbase, forced_batch_num) VALUES ($1, $2, $3, $4, $5)" + e := p.getExecQuerier(dbTx) _, err := e.Exec( ctx, openBatchSQL, @@ -843,13 +963,24 @@ func (p *PostgresStorage) openBatch(ctx context.Context, batchContext Processing batchContext.GlobalExitRoot.String(), batchContext.Timestamp.UTC(), batchContext.Coinbase.String(), + batchContext.ForcedBatchNum, ) return err } -func (p *PostgresStorage) closeBatch(ctx context.Context, receipt ProcessingReceipt, rawTxs []byte, dbTx pgx.Tx) error { +func (p *PostgresStorage) closeBatch(ctx context.Context, receipt ProcessingReceipt, dbTx pgx.Tx) error { + const closeBatchSQL = `UPDATE state.batch + SET state_root = $1, local_exit_root = $2, acc_input_hash = $3, raw_txs_data = $4, batch_resources = $5, closing_reason = $6 + WHERE batch_num = $7` + e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, closeBatchSQL, receipt.StateRoot.String(), receipt.LocalExitRoot.String(), rawTxs, receipt.BatchNumber) + batchResourcesJsonBytes, err := json.Marshal(receipt.BatchResources) + if err != nil { + return err + } + _, err = e.Exec(ctx, closeBatchSQL, receipt.StateRoot.String(), receipt.LocalExitRoot.String(), + receipt.AccInputHash.String(), receipt.BatchL2Data, string(batchResourcesJsonBytes), receipt.ClosingReason, receipt.BatchNumber) + return err } @@ -876,7 +1007,7 @@ func (p *PostgresStorage) UpdateGERInOpenBatch(ctx context.Context, ger common.H } if isBatchHasTxs { - return errors.New("batch has txs, can't change GER") + return errors.New("batch has txs, can't change globalExitRoot") } const updateGER = ` @@ -891,6 +1022,8 @@ func (p *PostgresStorage) UpdateGERInOpenBatch(ctx context.Context, ger common.H // IsBatchClosed indicates if the batch referenced by batchNum is closed or not func (p *PostgresStorage) IsBatchClosed(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (bool, error) { + const isBatchClosedSQL = "SELECT global_exit_root IS NOT NULL AND state_root IS NOT NULL FROM state.batch WHERE batch_num = $1 LIMIT 1" + q := p.getExecQuerier(dbTx) var isClosed bool err := q.QueryRow(ctx, isBatchClosedSQL, batchNum).Scan(&isClosed) @@ -899,6 +1032,12 @@ func (p *PostgresStorage) IsBatchClosed(ctx context.Context, batchNum uint64, db // GetNextForcedBatches gets the next forced batches from the queue. func (p *PostgresStorage) GetNextForcedBatches(ctx context.Context, nextForcedBatches int, dbTx pgx.Tx) ([]ForcedBatch, error) { + const getNextForcedBatchesSQL = ` + SELECT forced_batch_num, global_exit_root, timestamp, raw_txs_data, coinbase, block_num + FROM state.forced_batch + WHERE forced_batch_num > (Select coalesce(max(forced_batch_num),0) as forced_batch_num from state.batch INNER JOIN state.virtual_batch ON state.virtual_batch.batch_num = state.batch.batch_num) + ORDER BY forced_batch_num ASC LIMIT $1; + ` q := p.getExecQuerier(dbTx) // Get the next forced batches rows, err := q.Query(ctx, getNextForcedBatchesSQL, nextForcedBatches) @@ -919,7 +1058,7 @@ func (p *PostgresStorage) GetNextForcedBatches(ctx context.Context, nextForcedBa rawTxs string seq string ) - err := rows.Scan(&forcedBatch.ForcedBatchNumber, &globalExitRoot, &forcedBatch.ForcedAt, &rawTxs, &seq, &forcedBatch.BatchNumber, &forcedBatch.BlockNumber) + err := rows.Scan(&forcedBatch.ForcedBatchNumber, &globalExitRoot, &forcedBatch.ForcedAt, &rawTxs, &seq, &forcedBatch.BlockNumber) if err != nil { return nil, err } @@ -935,15 +1074,42 @@ func (p *PostgresStorage) GetNextForcedBatches(ctx context.Context, nextForcedBa return batches, nil } -// AddBatchNumberInForcedBatch updates the forced_batch table with the batchNumber. -func (p *PostgresStorage) AddBatchNumberInForcedBatch(ctx context.Context, forceBatchNumber, batchNumber uint64, dbTx pgx.Tx) error { - e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addBatchNumberInForcedBatchSQL, forceBatchNumber, batchNumber) - return err +// GetBatchNumberOfL2Block gets a batch number for l2 block by its number +func (p *PostgresStorage) GetBatchNumberOfL2Block(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { + getBatchNumByBlockNum := "SELECT batch_num FROM state.l2block WHERE block_num = $1" + batchNumber := uint64(0) + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, getBatchNumByBlockNum, blockNumber). + Scan(&batchNumber) + + if errors.Is(err, pgx.ErrNoRows) { + return batchNumber, ErrNotFound + } else if err != nil { + return batchNumber, err + } + return batchNumber, nil +} + +// BatchNumberByL2BlockNumber gets a batch number by a l2 block number +func (p *PostgresStorage) BatchNumberByL2BlockNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { + getBatchNumByBlockNum := "SELECT batch_num FROM state.l2block WHERE block_num = $1" + batchNumber := uint64(0) + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, getBatchNumByBlockNum, blockNumber). + Scan(&batchNumber) + + if errors.Is(err, pgx.ErrNoRows) { + return batchNumber, ErrNotFound + } else if err != nil { + return batchNumber, err + } + return batchNumber, nil } // GetL2BlockByNumber gets a l2 block by its number func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Block, error) { + const getL2BlockByNumberSQL = "SELECT header, uncles, received_at FROM state.l2block b WHERE b.block_num = $1" + header := &types.Header{} uncles := []*types.Header{} receivedAt := time.Time{} @@ -969,9 +1135,22 @@ func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber ui return block, nil } +// GetLastL2BlockCreatedAt gets the timestamp of the last l2 block +func (p *PostgresStorage) GetLastL2BlockCreatedAt(ctx context.Context, dbTx pgx.Tx) (*time.Time, error) { + var createdAt time.Time + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, "SELECT created_at FROM state.l2block b order by b.block_num desc LIMIT 1").Scan(&createdAt) + if err != nil { + return nil, err + } + return &createdAt, nil +} + // GetTransactionByHash gets a transaction accordingly to the provided transaction hash func (p *PostgresStorage) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) { var encoded string + const getTransactionByHashSQL = "SELECT transaction.encoded FROM state.transaction WHERE hash = $1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getTransactionByHashSQL, transactionHash.String()).Scan(&encoded) @@ -995,16 +1174,18 @@ func (p *PostgresStorage) GetTransactionReceipt(ctx context.Context, transaction var l2BlockNum uint64 const getReceiptSQL = ` - SELECT r.tx_hash - , r.type - , r.post_state - , r.status - , r.cumulative_gas_used - , r.gas_used - , r.contract_address - , t.encoded - , t.l2_block_num - , b.block_hash + SELECT + r.tx_index, + r.tx_hash, + r.type, + r.post_state, + r.status, + r.cumulative_gas_used, + r.gas_used, + r.contract_address, + t.encoded, + t.l2_block_num, + b.block_hash FROM state.receipt r INNER JOIN state.transaction t ON t.hash = r.tx_hash @@ -1015,7 +1196,8 @@ func (p *PostgresStorage) GetTransactionReceipt(ctx context.Context, transaction receipt := types.Receipt{} q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getReceiptSQL, transactionHash.String()). - Scan(&txHash, + Scan(&receipt.TransactionIndex, + &txHash, &receipt.Type, &receipt.PostState, &receipt.Status, @@ -1043,7 +1225,6 @@ func (p *PostgresStorage) GetTransactionReceipt(ctx context.Context, transaction receipt.BlockNumber = big.NewInt(0).SetUint64(l2BlockNum) receipt.BlockHash = common.HexToHash(l2BlockHash) - receipt.TransactionIndex = 0 receipt.Logs = logs receipt.Bloom = types.CreateBloom(types.Receipts{&receipt}) @@ -1056,7 +1237,16 @@ func (p *PostgresStorage) GetTransactionReceipt(ctx context.Context, transaction func (p *PostgresStorage) GetTransactionByL2BlockHashAndIndex(ctx context.Context, blockHash common.Hash, index uint64, dbTx pgx.Tx) (*types.Transaction, error) { var encoded string q := p.getExecQuerier(dbTx) - err := q.QueryRow(ctx, getTransactionByL2BlockHashAndIndexSQL, blockHash.String(), index).Scan(&encoded) + const query = ` + SELECT t.encoded + FROM state.transaction t + INNER JOIN state.l2block b + ON t.l2_block_num = b.block_num + INNER JOIN state.receipt r + ON r.tx_hash = t.hash + WHERE b.block_hash = $1 + AND r.tx_index = $2` + err := q.QueryRow(ctx, query, blockHash.String(), index).Scan(&encoded) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { @@ -1075,6 +1265,8 @@ func (p *PostgresStorage) GetTransactionByL2BlockHashAndIndex(ctx context.Contex // since we only have a single transaction per l2 block, any index different from 0 will return a not found result func (p *PostgresStorage) GetTransactionByL2BlockNumberAndIndex(ctx context.Context, blockNumber uint64, index uint64, dbTx pgx.Tx) (*types.Transaction, error) { var encoded string + const getTransactionByL2BlockNumberAndIndexSQL = "SELECT t.encoded FROM state.transaction t WHERE t.l2_block_num = $1 AND 0 = $2" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getTransactionByL2BlockNumberAndIndexSQL, blockNumber, index).Scan(&encoded) if errors.Is(err, pgx.ErrNoRows) { @@ -1094,6 +1286,8 @@ func (p *PostgresStorage) GetTransactionByL2BlockNumberAndIndex(ctx context.Cont // GetL2BlockTransactionCountByHash returns the number of transactions related to the provided block hash func (p *PostgresStorage) GetL2BlockTransactionCountByHash(ctx context.Context, blockHash common.Hash, dbTx pgx.Tx) (uint64, error) { var count uint64 + const getL2BlockTransactionCountByHashSQL = "SELECT COUNT(*) FROM state.transaction t INNER JOIN state.l2block b ON b.block_num = t.l2_block_num WHERE b.block_hash = $1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getL2BlockTransactionCountByHashSQL, blockHash.String()).Scan(&count) if err != nil { @@ -1105,6 +1299,8 @@ func (p *PostgresStorage) GetL2BlockTransactionCountByHash(ctx context.Context, // GetL2BlockTransactionCountByNumber returns the number of transactions related to the provided block number func (p *PostgresStorage) GetL2BlockTransactionCountByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { var count uint64 + const getL2BlockTransactionCountByNumberSQL = "SELECT COUNT(*) FROM state.transaction t WHERE t.l2_block_num = $1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getL2BlockTransactionCountByNumberSQL, blockNumber).Scan(&count) if err != nil { @@ -1122,7 +1318,8 @@ func (p *PostgresStorage) getTransactionLogs(ctx context.Context, transactionHas FROM state.log l INNER JOIN state.transaction t ON t.hash = l.tx_hash INNER JOIN state.l2block b ON b.block_num = t.l2_block_num - WHERE t.hash = $1` + WHERE t.hash = $1 + ORDER BY l.log_index ASC` rows, err := q.Query(ctx, getTransactionLogsSQL, transactionHash.String()) if !errors.Is(err, pgx.ErrNoRows) && err != nil { return nil, err @@ -1141,8 +1338,8 @@ func scanLogs(rows pgx.Rows) ([]*types.Log, error) { } var log types.Log - var blockHash, txHash, logAddress, logData, topic0 string - var topic1, topic2, topic3 *string + var blockHash, txHash, logAddress, logData string + var topic0, topic1, topic2, topic3 *string err := rows.Scan(&log.BlockNumber, &blockHash, &txHash, &log.Index, &logAddress, &logData, &topic0, &topic1, &topic2, &topic3) @@ -1158,7 +1355,12 @@ func scanLogs(rows pgx.Rows) ([]*types.Log, error) { if err != nil { return nil, err } - log.Topics = []common.Hash{common.HexToHash(topic0)} + + log.Topics = []common.Hash{} + if topic0 != nil { + log.Topics = append(log.Topics, common.HexToHash(*topic0)) + } + if topic1 != nil { log.Topics = append(log.Topics, common.HexToHash(*topic1)) } @@ -1185,9 +1387,10 @@ func scanLogs(rows pgx.Rows) ([]*types.Log, error) { func (p *PostgresStorage) AddL2Block(ctx context.Context, batchNumber uint64, l2Block *types.Block, receipts []*types.Receipt, dbTx pgx.Tx) error { e := p.getExecQuerier(dbTx) + const addTransactionSQL = "INSERT INTO state.transaction (hash, encoded, decoded, l2_block_num) VALUES($1, $2, $3, $4)" const addL2BlockSQL = ` - INSERT INTO state.l2block (block_num, block_hash, header, uncles, parent_hash, state_root, received_at, batch_num) - VALUES ( $1, $2, $3, $4, $5, $6, $7, $8)` + INSERT INTO state.l2block (block_num, block_hash, header, uncles, parent_hash, state_root, received_at, batch_num, created_at) + VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9)` var header = "{}" if l2Block.Header() != nil { @@ -1210,7 +1413,7 @@ func (p *PostgresStorage) AddL2Block(ctx context.Context, batchNumber uint64, l2 if _, err := e.Exec(ctx, addL2BlockSQL, l2Block.Number().Uint64(), l2Block.Hash().String(), header, uncles, l2Block.ParentHash().String(), l2Block.Root().String(), - l2Block.ReceivedAt, batchNumber); err != nil { + l2Block.ReceivedAt, batchNumber, time.Now().UTC()); err != nil { return err } @@ -1249,9 +1452,38 @@ func (p *PostgresStorage) AddL2Block(ctx context.Context, batchNumber uint64, l2 return nil } +// GetLastVirtualizedL2BlockNumber gets the last l2 block verified +func (p *PostgresStorage) GetLastVirtualizedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + var lastVirtualizedBlockNumber uint64 + const getLastVirtualizedBlockNumberSQL = ` + SELECT b.block_num + FROM state.l2block b + INNER JOIN state.virtual_batch vb + ON vb.batch_num = b.batch_num + ORDER BY b.block_num DESC LIMIT 1` + + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, getLastVirtualizedBlockNumberSQL).Scan(&lastVirtualizedBlockNumber) + + if errors.Is(err, pgx.ErrNoRows) { + return 0, ErrNotFound + } else if err != nil { + return 0, err + } + + return lastVirtualizedBlockNumber, nil +} + // GetLastConsolidatedL2BlockNumber gets the last l2 block verified func (p *PostgresStorage) GetLastConsolidatedL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { var lastConsolidatedBlockNumber uint64 + const getLastConsolidatedBlockNumberSQL = ` + SELECT b.block_num + FROM state.l2block b + INNER JOIN state.verified_batch vb + ON vb.batch_num = b.batch_num + ORDER BY b.block_num DESC LIMIT 1` + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getLastConsolidatedBlockNumberSQL).Scan(&lastConsolidatedBlockNumber) @@ -1267,6 +1499,8 @@ func (p *PostgresStorage) GetLastConsolidatedL2BlockNumber(ctx context.Context, // GetLastL2BlockNumber gets the last l2 block number func (p *PostgresStorage) GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { var lastBlockNumber uint64 + const getLastL2BlockNumber = "SELECT block_num FROM state.l2block ORDER BY block_num DESC LIMIT 1" + q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getLastL2BlockNumber).Scan(&lastBlockNumber) @@ -1281,9 +1515,10 @@ func (p *PostgresStorage) GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) // GetLastL2BlockHeader gets the last l2 block number func (p *PostgresStorage) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) (*types.Header, error) { + const query = "SELECT b.header FROM state.l2block b ORDER BY b.block_num DESC LIMIT 1" header := &types.Header{} q := p.getExecQuerier(dbTx) - err := q.QueryRow(ctx, getLastVirtualBlockHeaderSQL).Scan(&header) + err := q.QueryRow(ctx, query).Scan(&header) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrStateNotSynchronized @@ -1296,6 +1531,7 @@ func (p *PostgresStorage) GetLastL2BlockHeader(ctx context.Context, dbTx pgx.Tx) // GetLastL2Block retrieves the latest L2 Block from the State data base func (p *PostgresStorage) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*types.Block, error) { + const getLastL2BlockSQL = "SELECT header, uncles, received_at FROM state.l2block b ORDER BY b.block_num DESC LIMIT 1" var ( headerStr string unclesStr string @@ -1334,18 +1570,6 @@ func (p *PostgresStorage) GetLastL2Block(ctx context.Context, dbTx pgx.Tx) (*typ return block, nil } -// GetLastVerifiedBatchNumberSeenOnEthereum gets last verified batch number seen on ethereum -func (p *PostgresStorage) GetLastVerifiedBatchNumberSeenOnEthereum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { - const getLastVerifiedBatchSeenSQL = "SELECT last_batch_num_verified FROM state.sync_info LIMIT 1" - var batchNumber uint64 - e := p.getExecQuerier(dbTx) - err := e.QueryRow(ctx, getLastVerifiedBatchSeenSQL).Scan(&batchNumber) - if err != nil { - return 0, err - } - return batchNumber, nil -} - // GetLastVerifiedBatch gets last verified batch func (p *PostgresStorage) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*VerifiedBatch, error) { const query = "SELECT block_num, batch_num, tx_hash, aggregator FROM state.verified_batch ORDER BY batch_num DESC LIMIT 1" @@ -1409,6 +1633,8 @@ func (p *PostgresStorage) GetBlockNumVirtualBatchByBatchNum(ctx context.Context, // GetL2BlockByHash gets a l2 block from its hash func (p *PostgresStorage) GetL2BlockByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*types.Block, error) { + const getL2BlockByHashSQL = "SELECT header, uncles, received_at FROM state.l2block b WHERE b.block_hash = $1" + header := &types.Header{} uncles := []*types.Header{} receivedAt := time.Time{} @@ -1436,6 +1662,8 @@ func (p *PostgresStorage) GetL2BlockByHash(ctx context.Context, hash common.Hash // GetTxsByBlockNumber returns all the txs in a given block func (p *PostgresStorage) GetTxsByBlockNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) ([]*types.Transaction, error) { + const getTxsByBlockNumSQL = "SELECT encoded FROM state.transaction WHERE l2_block_num = $1" + q := p.getExecQuerier(dbTx) rows, err := q.Query(ctx, getTxsByBlockNumSQL, blockNumber) @@ -1464,8 +1692,48 @@ func (p *PostgresStorage) GetTxsByBlockNumber(ctx context.Context, blockNumber u return txs, nil } +// GetTxsByBatchNumber returns all the txs in a given batch +func (p *PostgresStorage) GetTxsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]*types.Transaction, error) { + q := p.getExecQuerier(dbTx) + + const getTxsByBatchNumSQL = ` + SELECT encoded + FROM state.transaction t + INNER JOIN state.l2block b + ON b.block_num = t.l2_block_num + WHERE b.batch_num = $1` + + rows, err := q.Query(ctx, getTxsByBatchNumSQL, batchNumber) + + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrNotFound + } else if err != nil { + return nil, err + } + + defer rows.Close() + + txs := make([]*types.Transaction, 0, len(rows.RawValues())) + var encoded string + for rows.Next() { + if err = rows.Scan(&encoded); err != nil { + return nil, err + } + + tx, err := DecodeTx(encoded) + if err != nil { + return nil, err + } + txs = append(txs, tx) + } + + return txs, nil +} + // GetL2BlockHeaderByHash gets the block header by block number func (p *PostgresStorage) GetL2BlockHeaderByHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (*types.Header, error) { + const getL2BlockHeaderByHashSQL = "SELECT header FROM state.l2block b WHERE b.block_hash = $1" + header := &types.Header{} q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getL2BlockHeaderByHashSQL, hash.String()).Scan(&header) @@ -1480,6 +1748,8 @@ func (p *PostgresStorage) GetL2BlockHeaderByHash(ctx context.Context, hash commo // GetL2BlockHeaderByNumber gets the block header by block number func (p *PostgresStorage) GetL2BlockHeaderByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*types.Header, error) { + const getL2BlockHeaderByNumberSQL = "SELECT header FROM state.l2block b WHERE b.block_num = $1" + header := &types.Header{} q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getL2BlockHeaderByNumberSQL, blockNumber).Scan(&header) @@ -1494,6 +1764,8 @@ func (p *PostgresStorage) GetL2BlockHeaderByNumber(ctx context.Context, blockNum // GetL2BlockHashesSince gets the block hashes added since the provided date func (p *PostgresStorage) GetL2BlockHashesSince(ctx context.Context, since time.Time, dbTx pgx.Tx) ([]common.Hash, error) { + const getL2BlockHashesSinceSQL = "SELECT block_hash FROM state.l2block WHERE created_at >= $1" + q := p.getExecQuerier(dbTx) rows, err := q.Query(ctx, getL2BlockHashesSinceSQL, since) if errors.Is(err, pgx.ErrNoRows) { @@ -1519,7 +1791,9 @@ func (p *PostgresStorage) GetL2BlockHashesSince(ctx context.Context, since time. } // IsL2BlockConsolidated checks if the block ID is consolidated -func (p *PostgresStorage) IsL2BlockConsolidated(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) { +func (p *PostgresStorage) IsL2BlockConsolidated(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) { + const isL2BlockConsolidated = "SELECT l2b.block_num FROM state.l2block l2b INNER JOIN state.verified_batch vb ON vb.batch_num = l2b.batch_num WHERE l2b.block_num = $1" + q := p.getExecQuerier(dbTx) rows, err := q.Query(ctx, isL2BlockConsolidated, blockNumber) if err != nil { @@ -1536,7 +1810,9 @@ func (p *PostgresStorage) IsL2BlockConsolidated(ctx context.Context, blockNumber } // IsL2BlockVirtualized checks if the block ID is virtualized -func (p *PostgresStorage) IsL2BlockVirtualized(ctx context.Context, blockNumber int, dbTx pgx.Tx) (bool, error) { +func (p *PostgresStorage) IsL2BlockVirtualized(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error) { + const isL2BlockVirtualized = "SELECT l2b.block_num FROM state.l2block l2b INNER JOIN state.virtual_batch vb ON vb.batch_num = l2b.batch_num WHERE l2b.block_num = $1" + q := p.getExecQuerier(dbTx) rows, err := q.Query(ctx, isL2BlockVirtualized, blockNumber) if err != nil { @@ -1559,7 +1835,8 @@ func (p *PostgresStorage) GetLogs(ctx context.Context, fromBlock uint64, toBlock FROM state.log l INNER JOIN state.transaction t ON t.hash = l.tx_hash INNER JOIN state.l2block b ON b.block_num = t.l2_block_num - WHERE b.block_hash = $1` + WHERE b.block_hash = $1 + ORDER BY b.block_num ASC, l.log_index ASC` const getLogsByFilterSQL = ` SELECT t.l2_block_num, b.block_hash, l.tx_hash, l.log_index, l.address, l.data, l.topic0, l.topic1, l.topic2, l.topic3 FROM state.log l @@ -1570,8 +1847,8 @@ func (p *PostgresStorage) GetLogs(ctx context.Context, fromBlock uint64, toBlock AND (l.topic1 = any($5) OR $5 IS NULL) AND (l.topic2 = any($6) OR $6 IS NULL) AND (l.topic3 = any($7) OR $7 IS NULL) - AND (b.received_at >= $8 OR $8 IS NULL) - ORDER BY b.block_num ASC` + AND (b.created_at >= $8 OR $8 IS NULL) + ORDER BY b.block_num ASC, l.log_index ASC` var err error var rows pgx.Rows @@ -1609,6 +1886,21 @@ func (p *PostgresStorage) GetLogs(ctx context.Context, fromBlock uint64, toBlock // GetSyncingInfo returns information regarding the syncing status of the node func (p *PostgresStorage) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (SyncingInfo, error) { var info SyncingInfo + const getSyncingInfoSQL = ` + SELECT coalesce(MIN(initial_blocks.block_num), 0) as init_sync_block + , coalesce(MAX(virtual_blocks.block_num), 0) as last_block_num_seen + , coalesce(MAX(consolidated_blocks.block_num), 0) as last_block_num_consolidated + , coalesce(MIN(sy.init_sync_batch), 0) as init_sync_batch + , coalesce(MIN(sy.last_batch_num_seen), 0) as last_batch_num_seen + , coalesce(MIN(sy.last_batch_num_consolidated), 0) as last_batch_num_consolidated + FROM state.sync_info sy + INNER JOIN state.l2block initial_blocks + ON initial_blocks.batch_num = sy.init_sync_batch + INNER JOIN state.l2block virtual_blocks + ON virtual_blocks.batch_num = sy.last_batch_num_seen + INNER JOIN state.l2block consolidated_blocks + ON consolidated_blocks.batch_num = sy.last_batch_num_consolidated; + ` q := p.getExecQuerier(dbTx) err := q.QueryRow(ctx, getSyncingInfoSQL). Scan(&info.InitialSyncingBlock, &info.LastBlockNumberSeen, &info.LastBlockNumberConsolidated, @@ -1684,51 +1976,137 @@ func (p *PostgresStorage) AddLog(ctx context.Context, l *types.Log, dbTx pgx.Tx) // a global exit root number. func (p *PostgresStorage) GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*GlobalExitRoot, error) { var ( - exitRoot GlobalExitRoot - globalNum uint64 - err error + exitRoot GlobalExitRoot + err error ) - const sql = "SELECT block_num, global_exit_root_num, mainnet_exit_root, rollup_exit_root, global_exit_root FROM state.exit_root WHERE global_exit_root = $1 ORDER BY block_num DESC LIMIT 1" + const sql = "SELECT block_num, mainnet_exit_root, rollup_exit_root, global_exit_root FROM state.exit_root WHERE global_exit_root = $1 ORDER BY id DESC LIMIT 1" e := p.getExecQuerier(dbTx) - err = e.QueryRow(ctx, sql, ger).Scan(&exitRoot.BlockNumber, &globalNum, &exitRoot.MainnetExitRoot, &exitRoot.RollupExitRoot, &exitRoot.GlobalExitRoot) + err = e.QueryRow(ctx, sql, ger).Scan(&exitRoot.BlockNumber, &exitRoot.MainnetExitRoot, &exitRoot.RollupExitRoot, &exitRoot.GlobalExitRoot) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { return nil, err } - exitRoot.GlobalExitRootNum = new(big.Int).SetUint64(globalNum) return &exitRoot, nil } -// AddGeneratedProof adds a generated proof to the storage -func (p *PostgresStorage) AddGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error { - const addGeneratedProofSQL = "INSERT INTO state.proof (batch_num, proof) VALUES ($1, $2)" +// AddSequence stores the sequence information to allow the aggregator verify sequences. +func (p *PostgresStorage) AddSequence(ctx context.Context, sequence Sequence, dbTx pgx.Tx) error { + const addSequenceSQL = "INSERT INTO state.sequences (from_batch_num, to_batch_num) VALUES($1, $2)" + e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addGeneratedProofSQL, batchNumber, proof) + _, err := e.Exec(ctx, addSequenceSQL, sequence.FromBatchNumber, sequence.ToBatchNumber) return err } -// UpdateGeneratedProof updates a generated proof in the storage -func (p *PostgresStorage) UpdateGeneratedProof(ctx context.Context, batchNumber uint64, proof *pb.GetProofResponse, dbTx pgx.Tx) error { - const addGeneratedProofSQL = "UPDATE state.proof SET proof = $2 WHERE batch_num = $1" +// GetSequences get the next sequences higher than an specify batch number +func (p *PostgresStorage) GetSequences(ctx context.Context, lastVerifiedBatchNumber uint64, dbTx pgx.Tx) ([]Sequence, error) { + const getSequencesSQL = "SELECT from_batch_num, to_batch_num FROM state.sequences WHERE from_batch_num >= $1 ORDER BY from_batch_num ASC" + q := p.getExecQuerier(dbTx) + + rows, err := q.Query(ctx, getSequencesSQL, lastVerifiedBatchNumber) + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrStateNotSynchronized + } else if err != nil { + return nil, err + } + defer rows.Close() + + sequences := make([]Sequence, 0, len(rows.RawValues())) + + for rows.Next() { + var sequence Sequence + if err := rows.Scan( + &sequence.FromBatchNumber, + &sequence.ToBatchNumber, + ); err != nil { + return sequences, err + } + sequences = append(sequences, sequence) + } + return sequences, err +} + +// GetVirtualBatchToProve return the next batch that is not proved, neither in +// proved process. +func (p *PostgresStorage) GetVirtualBatchToProve(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*Batch, error) { + const query = ` + SELECT + b.batch_num, + b.global_exit_root, + b.local_exit_root, + b.acc_input_hash, + b.state_root, + b.timestamp, + b.coinbase, + b.raw_txs_data, + b.forced_batch_num + FROM + state.batch b, + state.virtual_batch v + WHERE + b.batch_num > $1 AND b.batch_num = v.batch_num AND + NOT EXISTS ( + SELECT p.batch_num FROM state.proof p + WHERE v.batch_num >= p.batch_num AND v.batch_num <= p.batch_num_final + ) + ORDER BY b.batch_num ASC LIMIT 1 + ` e := p.getExecQuerier(dbTx) - _, err := e.Exec(ctx, addGeneratedProofSQL, batchNumber, proof) - return err + row := e.QueryRow(ctx, query, lastVerfiedBatchNumber) + batch, err := scanBatch(row) + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrNotFound + } else if err != nil { + return nil, err + } + return &batch, nil } -// GetGeneratedProofByBatchNumber gets a generated proof from the storage -func (p *PostgresStorage) GetGeneratedProofByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*pb.GetProofResponse, error) { - var ( - proof *pb.GetProofResponse - err error - ) +// CheckProofContainsCompleteSequences checks if a recursive proof contains complete sequences +func (p *PostgresStorage) CheckProofContainsCompleteSequences(ctx context.Context, proof *Proof, dbTx pgx.Tx) (bool, error) { + const getProofContainsCompleteSequencesSQL = ` + SELECT EXISTS (SELECT 1 FROM state.sequences s1 WHERE s1.from_batch_num = $1) AND + EXISTS (SELECT 1 FROM state.sequences s2 WHERE s2.to_batch_num = $2) + ` + e := p.getExecQuerier(dbTx) + var exists bool + err := e.QueryRow(ctx, getProofContainsCompleteSequencesSQL, proof.BatchNumber, proof.BatchNumberFinal).Scan(&exists) + if err != nil && !errors.Is(err, pgx.ErrNoRows) { + return exists, err + } + return exists, nil +} + +// GetProofReadyToVerify return the proof that is ready to verify +func (p *PostgresStorage) GetProofReadyToVerify(ctx context.Context, lastVerfiedBatchNumber uint64, dbTx pgx.Tx) (*Proof, error) { + const getProofReadyToVerifySQL = ` + SELECT + p.batch_num, + p.batch_num_final, + p.proof, + p.proof_id, + p.input_prover, + p.prover, + p.prover_id, + p.generating_since, + p.created_at, + p.updated_at + FROM state.proof p + WHERE batch_num = $1 AND generating_since IS NULL AND + EXISTS (SELECT 1 FROM state.sequences s1 WHERE s1.from_batch_num = p.batch_num) AND + EXISTS (SELECT 1 FROM state.sequences s2 WHERE s2.to_batch_num = p.batch_num_final) + ` + + var proof *Proof = &Proof{} - const getGeneratedProofSQL = "SELECT proof FROM state.proof WHERE batch_num = $1" e := p.getExecQuerier(dbTx) - err = e.QueryRow(ctx, getGeneratedProofSQL, batchNumber).Scan(&proof) + row := e.QueryRow(ctx, getProofReadyToVerifySQL, lastVerfiedBatchNumber+1) + err := row.Scan(&proof.BatchNumber, &proof.BatchNumberFinal, &proof.Proof, &proof.ProofID, &proof.InputProver, &proof.Prover, &proof.ProverID, &proof.GeneratingSince, &proof.CreatedAt, &proof.UpdatedAt) + if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } else if err != nil { @@ -1738,19 +2116,280 @@ func (p *PostgresStorage) GetGeneratedProofByBatchNumber(ctx context.Context, ba return proof, err } -// DeleteGeneratedProof deletes a generated proof from the storage -func (p *PostgresStorage) DeleteGeneratedProof(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { - const deleteGeneratedProofSQL = "DELETE FROM state.proof WHERE batch_num = $1" +// GetProofsToAggregate return the next to proof that it is possible to aggregate +func (p *PostgresStorage) GetProofsToAggregate(ctx context.Context, dbTx pgx.Tx) (*Proof, *Proof, error) { + var ( + proof1 *Proof = &Proof{} + proof2 *Proof = &Proof{} + ) + + // TODO: add comments to explain the query + const getProofsToAggregateSQL = ` + SELECT + p1.batch_num as p1_batch_num, + p1.batch_num_final as p1_batch_num_final, + p1.proof as p1_proof, + p1.proof_id as p1_proof_id, + p1.input_prover as p1_input_prover, + p1.prover as p1_prover, + p1.prover_id as p1_prover_id, + p1.generating_since as p1_generating_since, + p1.created_at as p1_created_at, + p1.updated_at as p1_updated_at, + p2.batch_num as p2_batch_num, + p2.batch_num_final as p2_batch_num_final, + p2.proof as p2_proof, + p2.proof_id as p2_proof_id, + p2.input_prover as p2_input_prover, + p2.prover as p2_prover, + p2.prover_id as p2_prover_id, + p2.generating_since as p2_generating_since, + p2.created_at as p2_created_at, + p2.updated_at as p2_updated_at + FROM state.proof p1 INNER JOIN state.proof p2 ON p1.batch_num_final = p2.batch_num - 1 + WHERE p1.generating_since IS NULL AND p2.generating_since IS NULL AND + p1.proof IS NOT NULL AND p2.proof IS NOT NULL AND + ( + EXISTS ( + SELECT 1 FROM state.sequences s + WHERE p1.batch_num >= s.from_batch_num AND p1.batch_num <= s.to_batch_num AND + p1.batch_num_final >= s.from_batch_num AND p1.batch_num_final <= s.to_batch_num AND + p2.batch_num >= s.from_batch_num AND p2.batch_num <= s.to_batch_num AND + p2.batch_num_final >= s.from_batch_num AND p2.batch_num_final <= s.to_batch_num + ) + OR + ( + EXISTS ( SELECT 1 FROM state.sequences s WHERE p1.batch_num = s.from_batch_num) AND + EXISTS ( SELECT 1 FROM state.sequences s WHERE p1.batch_num_final = s.to_batch_num) AND + EXISTS ( SELECT 1 FROM state.sequences s WHERE p2.batch_num = s.from_batch_num) AND + EXISTS ( SELECT 1 FROM state.sequences s WHERE p2.batch_num_final = s.to_batch_num) + ) + ) + ORDER BY p1.batch_num ASC + LIMIT 1 + ` + + e := p.getExecQuerier(dbTx) + row := e.QueryRow(ctx, getProofsToAggregateSQL) + err := row.Scan( + &proof1.BatchNumber, &proof1.BatchNumberFinal, &proof1.Proof, &proof1.ProofID, &proof1.InputProver, &proof1.Prover, &proof1.ProverID, &proof1.GeneratingSince, &proof1.CreatedAt, &proof1.UpdatedAt, + &proof2.BatchNumber, &proof2.BatchNumberFinal, &proof2.Proof, &proof2.ProofID, &proof2.InputProver, &proof2.Prover, &proof2.ProverID, &proof2.GeneratingSince, &proof2.CreatedAt, &proof2.UpdatedAt) + + if errors.Is(err, pgx.ErrNoRows) { + return nil, nil, ErrNotFound + } else if err != nil { + return nil, nil, err + } + + return proof1, proof2, err +} + +// AddGeneratedProof adds a generated proof to the storage +func (p *PostgresStorage) AddGeneratedProof(ctx context.Context, proof *Proof, dbTx pgx.Tx) error { + const addGeneratedProofSQL = "INSERT INTO state.proof (batch_num, batch_num_final, proof, proof_id, input_prover, prover, prover_id, generating_since, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)" + e := p.getExecQuerier(dbTx) + now := time.Now().UTC().Round(time.Microsecond) + _, err := e.Exec(ctx, addGeneratedProofSQL, proof.BatchNumber, proof.BatchNumberFinal, proof.Proof, proof.ProofID, proof.InputProver, proof.Prover, proof.ProverID, proof.GeneratingSince, now, now) + return err +} + +// UpdateGeneratedProof updates a generated proof in the storage +func (p *PostgresStorage) UpdateGeneratedProof(ctx context.Context, proof *Proof, dbTx pgx.Tx) error { + const addGeneratedProofSQL = "UPDATE state.proof SET proof = $3, proof_id = $4, input_prover = $5, prover = $6, prover_id = $7, generating_since = $8, updated_at = $9 WHERE batch_num = $1 AND batch_num_final = $2" + e := p.getExecQuerier(dbTx) + now := time.Now().UTC().Round(time.Microsecond) + _, err := e.Exec(ctx, addGeneratedProofSQL, proof.BatchNumber, proof.BatchNumberFinal, proof.Proof, proof.ProofID, proof.InputProver, proof.Prover, proof.ProverID, proof.GeneratingSince, now) + return err +} + +// DeleteGeneratedProofs deletes from the storage the generated proofs falling +// inside the batch numbers range. +func (p *PostgresStorage) DeleteGeneratedProofs(ctx context.Context, batchNumber uint64, batchNumberFinal uint64, dbTx pgx.Tx) error { + const deleteGeneratedProofSQL = "DELETE FROM state.proof WHERE batch_num >= $1 AND batch_num_final <= $2" + e := p.getExecQuerier(dbTx) + _, err := e.Exec(ctx, deleteGeneratedProofSQL, batchNumber, batchNumberFinal) + return err +} + +// CleanupGeneratedProofs deletes from the storage the generated proofs up to +// the specified batch number included. +func (p *PostgresStorage) CleanupGeneratedProofs(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { + const deleteGeneratedProofSQL = "DELETE FROM state.proof WHERE batch_num_final <= $1" e := p.getExecQuerier(dbTx) _, err := e.Exec(ctx, deleteGeneratedProofSQL, batchNumber) return err } -// DeleteUngeneratedProofs deletes ungenerated proofs from state.proof table +// CleanupLockedProofs deletes from the storage the proofs locked in generating +// state for more than the provided threshold. +func (p *PostgresStorage) CleanupLockedProofs(ctx context.Context, duration string, dbTx pgx.Tx) (int64, error) { + interval, err := toPostgresInterval(duration) + if err != nil { + return 0, err + } + sql := fmt.Sprintf("DELETE FROM state.proof WHERE generating_since < (NOW() - interval '%s')", interval) + e := p.getExecQuerier(dbTx) + ct, err := e.Exec(ctx, sql) + if err != nil { + return 0, err + } + return ct.RowsAffected(), nil +} + +// DeleteUngeneratedProofs deletes ungenerated proofs. // This method is meant to be use during aggregator boot-up sequence func (p *PostgresStorage) DeleteUngeneratedProofs(ctx context.Context, dbTx pgx.Tx) error { - const deleteUngeneratedProofsSQL = "DELETE FROM state.proof WHERE proof is null" + const deleteUngeneratedProofsSQL = "DELETE FROM state.proof WHERE generating_since IS NOT NULL" e := p.getExecQuerier(dbTx) _, err := e.Exec(ctx, deleteUngeneratedProofsSQL) return err } + +// GetLastClosedBatch returns the latest closed batch +func (p *PostgresStorage) GetLastClosedBatch(ctx context.Context, dbTx pgx.Tx) (*Batch, error) { + const getLastClosedBatchSQL = ` + SELECT bt.batch_num, bt.global_exit_root, bt.local_exit_root, bt.acc_input_hash, bt.state_root, bt.timestamp, bt.coinbase, bt.raw_txs_data + FROM state.batch bt + WHERE global_exit_root IS NOT NULL AND state_root IS NOT NULL + ORDER BY bt.batch_num DESC + LIMIT 1;` + + e := p.getExecQuerier(dbTx) + row := e.QueryRow(ctx, getLastClosedBatchSQL) + batch, err := scanBatch(row) + + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrStateNotSynchronized + } else if err != nil { + return nil, err + } + return &batch, nil +} + +// UpdateBatchL2Data updates data tx data in a batch +func (p *PostgresStorage) UpdateBatchL2Data(ctx context.Context, batchNumber uint64, batchL2Data []byte, dbTx pgx.Tx) error { + const updateL2DataSQL = "UPDATE state.batch SET raw_txs_data = $2 WHERE batch_num = $1" + + e := p.getExecQuerier(dbTx) + _, err := e.Exec(ctx, updateL2DataSQL, batchNumber, batchL2Data) + return err +} + +// AddAccumulatedInputHash adds the accumulated input hash +func (p *PostgresStorage) AddAccumulatedInputHash(ctx context.Context, batchNum uint64, accInputHash common.Hash, dbTx pgx.Tx) error { + const addAccInputHashBatchSQL = "UPDATE state.batch SET acc_input_hash = $1 WHERE batch_num = $2" + e := p.getExecQuerier(dbTx) + _, err := e.Exec(ctx, addAccInputHashBatchSQL, accInputHash.String(), batchNum) + return err +} + +// GetLastTrustedForcedBatchNumber get last trusted forced batch number +func (p *PostgresStorage) GetLastTrustedForcedBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + const getLastTrustedForcedBatchNumberSQL = "SELECT COALESCE(MAX(forced_batch_num), 0) FROM state.batch" + var forcedBatchNumber uint64 + q := p.getExecQuerier(dbTx) + + err := q.QueryRow(ctx, getLastTrustedForcedBatchNumberSQL).Scan(&forcedBatchNumber) + if errors.Is(err, pgx.ErrNoRows) { + return 0, ErrStateNotSynchronized + } + return forcedBatchNumber, err +} + +// AddTrustedReorg is used to store trusted reorgs +func (p *PostgresStorage) AddTrustedReorg(ctx context.Context, reorg *TrustedReorg, dbTx pgx.Tx) error { + const insertTrustedReorgSQL = "INSERT INTO state.trusted_reorg (timestamp, batch_num, reason) VALUES (NOW(), $1, $2)" + + e := p.getExecQuerier(dbTx) + _, err := e.Exec(ctx, insertTrustedReorgSQL, reorg.BatchNumber, reorg.Reason) + return err +} + +// CountReorgs returns the number of reorgs +func (p *PostgresStorage) CountReorgs(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + const countReorgsSQL = "SELECT COUNT(*) FROM state.trusted_reorg" + + var count uint64 + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, countReorgsSQL).Scan(&count) + if err != nil { + return 0, err + } + return count, nil +} + +// GetForkIDTrustedReorgCount returns the forkID +func (p *PostgresStorage) GetForkIDTrustedReorgCount(ctx context.Context, forkID uint64, version string, dbTx pgx.Tx) (uint64, error) { + const forkIDTrustedReorgSQL = "SELECT COUNT(*) FROM state.trusted_reorg WHERE reason=$1" + + var count uint64 + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, forkIDTrustedReorgSQL, fmt.Sprintf("New ForkID: %d. Version: %s", forkID, version)).Scan(&count) + if err != nil { + return 0, err + } + return count, nil +} + +// GetReorgedTransactions returns the transactions that were reorged +func (p *PostgresStorage) GetReorgedTransactions(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]*types.Transaction, error) { + const getReorgedTransactionsSql = "SELECT encoded FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num >= $1 ORDER BY l2_block_num ASC" + e := p.getExecQuerier(dbTx) + rows, err := e.Query(ctx, getReorgedTransactionsSql, batchNumber) + if !errors.Is(err, pgx.ErrNoRows) && err != nil { + return nil, err + } + defer rows.Close() + + txs := make([]*types.Transaction, 0, len(rows.RawValues())) + + for rows.Next() { + if rows.Err() != nil { + return nil, rows.Err() + } + var encodedTx string + err := rows.Scan(&encodedTx) + if err != nil { + return nil, err + } + + tx, err := DecodeTx(encodedTx) + if err != nil { + return nil, err + } + txs = append(txs, tx) + } + return txs, nil +} + +// GetLatestGer is used to get the latest ger +func (p *PostgresStorage) GetLatestGer(ctx context.Context, maxBlockNumber uint64) (GlobalExitRoot, time.Time, error) { + ger, receivedAt, err := p.GetLatestGlobalExitRoot(ctx, maxBlockNumber, nil) + if err != nil && errors.Is(err, ErrNotFound) { + return GlobalExitRoot{}, time.Time{}, nil + } else if err != nil { + return GlobalExitRoot{}, time.Time{}, fmt.Errorf("failed to get latest global exit root, err: %w", err) + } else { + return ger, receivedAt, nil + } +} + +// GetBatchByForcedBatchNum returns the batch with the given forced batch number. +func (p *PostgresStorage) GetBatchByForcedBatchNum(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (*Batch, error) { + const getForcedBatchByNumberSQL = ` + SELECT batch_num, global_exit_root, local_exit_root, acc_input_hash, state_root, timestamp, coinbase, raw_txs_data, forced_batch_num + FROM state.batch + WHERE forced_batch_num = $1` + + e := p.getExecQuerier(dbTx) + row := e.QueryRow(ctx, getForcedBatchByNumberSQL, forcedBatchNumber) + batch, err := scanBatch(row) + + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrStateNotSynchronized + } else if err != nil { + return nil, err + } + + return &batch, nil +} diff --git a/state/pgstatestorage_test.go b/state/pgstatestorage_test.go new file mode 100644 index 0000000000..c1bd8197e1 --- /dev/null +++ b/state/pgstatestorage_test.go @@ -0,0 +1,439 @@ +package state_test + +import ( + "context" + "math" + "math/big" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/trie" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + pgStateStorage *state.PostgresStorage + block = &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } +) + +func setup() { + pgStateStorage = state.NewPostgresStorage(stateDb) +} + +func TestGetBatchByL2BlockNumber(t *testing.T) { + setup() + ctx := context.Background() + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + err = testState.AddBlock(ctx, block, dbTx) + assert.NoError(t, err) + + batchNumber := uint64(1) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES ($1)", batchNumber) + assert.NoError(t, err) + + time := time.Now() + blockNumber := big.NewInt(1) + + tx := types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: nil, + Value: new(big.Int), + Gas: 0, + GasPrice: big.NewInt(0), + }) + + receipt := &types.Receipt{ + Type: uint8(tx.Type()), + PostState: state.ZeroHash.Bytes(), + CumulativeGasUsed: 0, + BlockNumber: blockNumber, + GasUsed: tx.Gas(), + TxHash: tx.Hash(), + TransactionIndex: 0, + Status: types.ReceiptStatusSuccessful, + } + + header := &types.Header{ + Number: big.NewInt(1), + ParentHash: state.ZeroHash, + Coinbase: state.ZeroAddress, + Root: state.ZeroHash, + GasUsed: 1, + GasLimit: 10, + Time: uint64(time.Unix()), + } + transactions := []*types.Transaction{tx} + + receipts := []*types.Receipt{receipt} + + // Create block to be able to calculate its hash + l2Block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) + receipt.BlockHash = l2Block.Hash() + + err = pgStateStorage.AddL2Block(ctx, batchNumber, l2Block, receipts, dbTx) + require.NoError(t, err) + result, err := pgStateStorage.BatchNumberByL2BlockNumber(ctx, l2Block.Number().Uint64(), dbTx) + require.NoError(t, err) + assert.Equal(t, batchNumber, result) + require.NoError(t, dbTx.Commit(ctx)) +} + +func TestAddAndGetSequences(t *testing.T) { + initOrResetDB() + + ctx := context.Background() + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, dbTx) + assert.NoError(t, err) + + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (0)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (1)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (2)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (3)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (4)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (5)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (6)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (7)") + require.NoError(t, err) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (8)") + require.NoError(t, err) + + sequence := state.Sequence{ + FromBatchNumber: 0, + ToBatchNumber: 3, + } + err = testState.AddSequence(ctx, sequence, dbTx) + require.NoError(t, err) + + sequence2 := state.Sequence{ + FromBatchNumber: 3, + ToBatchNumber: 7, + } + err = testState.AddSequence(ctx, sequence2, dbTx) + require.NoError(t, err) + + sequence3 := state.Sequence{ + FromBatchNumber: 7, + ToBatchNumber: 8, + } + err = testState.AddSequence(ctx, sequence3, dbTx) + require.NoError(t, err) + + sequences, err := testState.GetSequences(ctx, 0, dbTx) + require.NoError(t, err) + require.Equal(t, 3, len(sequences)) + require.Equal(t, uint64(0), sequences[0].FromBatchNumber) + require.Equal(t, uint64(3), sequences[1].FromBatchNumber) + require.Equal(t, uint64(7), sequences[2].FromBatchNumber) + require.Equal(t, uint64(3), sequences[0].ToBatchNumber) + require.Equal(t, uint64(7), sequences[1].ToBatchNumber) + require.Equal(t, uint64(8), sequences[2].ToBatchNumber) + + sequences, err = testState.GetSequences(ctx, 3, dbTx) + require.NoError(t, err) + require.Equal(t, 2, len(sequences)) + require.Equal(t, uint64(3), sequences[0].FromBatchNumber) + require.Equal(t, uint64(7), sequences[1].FromBatchNumber) + require.Equal(t, uint64(7), sequences[0].ToBatchNumber) + require.Equal(t, uint64(8), sequences[1].ToBatchNumber) + + require.NoError(t, dbTx.Commit(ctx)) +} + +func TestAddGlobalExitRoot(t *testing.T) { + // Init database instance + initOrResetDB() + + ctx := context.Background() + tx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, tx) + assert.NoError(t, err) + globalExitRoot := state.GlobalExitRoot{ + BlockNumber: 1, + MainnetExitRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + RollupExitRoot: common.HexToHash("0x30a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0"), + GlobalExitRoot: common.HexToHash("0x40a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0"), + } + err = testState.AddGlobalExitRoot(ctx, &globalExitRoot, tx) + require.NoError(t, err) + exit, _, err := testState.GetLatestGlobalExitRoot(ctx, math.MaxInt64, tx) + require.NoError(t, err) + err = tx.Commit(ctx) + require.NoError(t, err) + assert.Equal(t, globalExitRoot.BlockNumber, exit.BlockNumber) + assert.Equal(t, globalExitRoot.MainnetExitRoot, exit.MainnetExitRoot) + assert.Equal(t, globalExitRoot.RollupExitRoot, exit.RollupExitRoot) + assert.Equal(t, globalExitRoot.GlobalExitRoot, exit.GlobalExitRoot) +} + +func TestVerifiedBatch(t *testing.T) { + initOrResetDB() + + ctx := context.Background() + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, dbTx) + assert.NoError(t, err) + //require.NoError(t, tx.Commit(ctx)) + + lastBlock, err := testState.GetLastBlock(ctx, dbTx) + assert.NoError(t, err) + assert.Equal(t, uint64(1), lastBlock.BlockNumber) + + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (1)") + + require.NoError(t, err) + virtualBatch := state.VirtualBatch{ + BlockNumber: 1, + BatchNumber: 1, + TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + } + err = testState.AddVirtualBatch(ctx, &virtualBatch, dbTx) + require.NoError(t, err) + expectedVerifiedBatch := state.VerifiedBatch{ + BlockNumber: 1, + BatchNumber: 1, + StateRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f2"), + Aggregator: common.HexToAddress("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + IsTrusted: true, + } + err = testState.AddVerifiedBatch(ctx, &expectedVerifiedBatch, dbTx) + require.NoError(t, err) + + // Step to create done, retrieve it + + actualVerifiedBatch, err := testState.GetVerifiedBatch(ctx, 1, dbTx) + require.NoError(t, err) + require.Equal(t, expectedVerifiedBatch, *actualVerifiedBatch) + + require.NoError(t, dbTx.Commit(ctx)) +} + +func TestAddAccumulatedInputHash(t *testing.T) { + initOrResetDB() + + ctx := context.Background() + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, dbTx) + assert.NoError(t, err) + + _, err = testState.PostgresStorage.Exec(ctx, `INSERT INTO state.batch + (batch_num, global_exit_root, local_exit_root, state_root, timestamp, coinbase, raw_txs_data) + VALUES(1, '0x0000000000000000000000000000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000000000000000000000000000', '0xbf34f9a52a63229e90d1016011655bc12140bba5b771817b88cbf340d08dcbde', '2022-12-19 08:17:45.000', '0x0000000000000000000000000000000000000000', NULL); + `) + require.NoError(t, err) + + accInputHash := common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f2") + batchNum := uint64(1) + err = testState.AddAccumulatedInputHash(ctx, batchNum, accInputHash, dbTx) + require.NoError(t, err) + + b, err := testState.GetBatchByNumber(ctx, batchNum, dbTx) + require.NoError(t, err) + assert.Equal(t, b.BatchNumber, batchNum) + assert.Equal(t, b.AccInputHash, accInputHash) + require.NoError(t, dbTx.Commit(ctx)) +} + +func TestForcedBatch(t *testing.T) { + // Init database instance + initOrResetDB() + + ctx := context.Background() + tx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, tx) + assert.NoError(t, err) + rtx := "29e885edaf8e4b51e1d2e05f9da28000000000000000000000000000000000000000000000000000000161d2fb4f6b1d53827d9b80a23cf2d7d9f1" + raw, err := hex.DecodeString(rtx) + assert.NoError(t, err) + forcedBatch := state.ForcedBatch{ + BlockNumber: 1, + ForcedBatchNumber: 1, + Sequencer: common.HexToAddress("0x2536C2745Ac4A584656A830f7bdCd329c94e8F30"), + RawTxsData: raw, + ForcedAt: time.Now(), + GlobalExitRoot: common.HexToHash("0x40a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0"), + } + err = testState.AddForcedBatch(ctx, &forcedBatch, tx) + require.NoError(t, err) + fb, err := testState.GetForcedBatch(ctx, 1, tx) + require.NoError(t, err) + err = tx.Commit(ctx) + require.NoError(t, err) + assert.Equal(t, forcedBatch.BlockNumber, fb.BlockNumber) + assert.Equal(t, forcedBatch.ForcedBatchNumber, fb.ForcedBatchNumber) + assert.Equal(t, forcedBatch.Sequencer, fb.Sequencer) + assert.Equal(t, forcedBatch.RawTxsData, fb.RawTxsData) + assert.Equal(t, rtx, common.Bytes2Hex(fb.RawTxsData)) + assert.Equal(t, forcedBatch.ForcedAt.Unix(), fb.ForcedAt.Unix()) + assert.Equal(t, forcedBatch.GlobalExitRoot, fb.GlobalExitRoot) +} +func TestCleanupLockedProofs(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + initOrResetDB() + ctx := context.Background() + batchNumber := uint64(42) + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES ($1), ($2), ($3)", batchNumber, batchNumber+1, batchNumber+2) + require.NoError(err) + const addGeneratedProofSQL = "INSERT INTO state.proof (batch_num, batch_num_final, proof, proof_id, input_prover, prover, prover_id, generating_since, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)" + // proof with `generating_since` older than interval + now := time.Now().Round(time.Microsecond) + oneHourAgo := now.Add(-time.Hour).Round(time.Microsecond) + olderProofID := "olderProofID" + olderProof := state.Proof{ + ProofID: &olderProofID, + BatchNumber: batchNumber, + BatchNumberFinal: batchNumber, + GeneratingSince: &oneHourAgo, + } + _, err := testState.PostgresStorage.Exec(ctx, addGeneratedProofSQL, olderProof.BatchNumber, olderProof.BatchNumberFinal, olderProof.Proof, olderProof.ProofID, olderProof.InputProver, olderProof.Prover, olderProof.ProverID, olderProof.GeneratingSince, oneHourAgo, oneHourAgo) + require.NoError(err) + // proof with `generating_since` newer than interval + newerProofID := "newerProofID" + newerProof := state.Proof{ + ProofID: &newerProofID, + BatchNumber: batchNumber + 1, + BatchNumberFinal: batchNumber + 1, + GeneratingSince: &now, + CreatedAt: oneHourAgo, + UpdatedAt: now, + } + _, err = testState.PostgresStorage.Exec(ctx, addGeneratedProofSQL, newerProof.BatchNumber, newerProof.BatchNumberFinal, newerProof.Proof, newerProof.ProofID, newerProof.InputProver, newerProof.Prover, newerProof.ProverID, newerProof.GeneratingSince, oneHourAgo, now) + require.NoError(err) + // proof with `generating_since` nil (currently not generating) + olderNotGenProofID := "olderNotGenProofID" + olderNotGenProof := state.Proof{ + ProofID: &olderNotGenProofID, + BatchNumber: batchNumber + 2, + BatchNumberFinal: batchNumber + 2, + CreatedAt: oneHourAgo, + UpdatedAt: oneHourAgo, + } + _, err = testState.PostgresStorage.Exec(ctx, addGeneratedProofSQL, olderNotGenProof.BatchNumber, olderNotGenProof.BatchNumberFinal, olderNotGenProof.Proof, olderNotGenProof.ProofID, olderNotGenProof.InputProver, olderNotGenProof.Prover, olderNotGenProof.ProverID, olderNotGenProof.GeneratingSince, oneHourAgo, oneHourAgo) + require.NoError(err) + + _, err = testState.CleanupLockedProofs(ctx, "1m", nil) + + require.NoError(err) + rows, err := testState.PostgresStorage.Query(ctx, "SELECT batch_num, batch_num_final, proof, proof_id, input_prover, prover, prover_id, generating_since, created_at, updated_at FROM state.proof") + require.NoError(err) + proofs := make([]state.Proof, 0, len(rows.RawValues())) + for rows.Next() { + var proof state.Proof + err := rows.Scan( + &proof.BatchNumber, + &proof.BatchNumberFinal, + &proof.Proof, + &proof.ProofID, + &proof.InputProver, + &proof.Prover, + &proof.ProverID, + &proof.GeneratingSince, + &proof.CreatedAt, + &proof.UpdatedAt, + ) + require.NoError(err) + proofs = append(proofs, proof) + } + assert.Len(proofs, 2) + assert.Contains(proofs, olderNotGenProof) + assert.Contains(proofs, newerProof) +} + +func TestVirtualBatch(t *testing.T) { + initOrResetDB() + + ctx := context.Background() + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + block := &state.Block{ + BlockNumber: 1, + BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + ReceivedAt: time.Now(), + } + err = testState.AddBlock(ctx, block, dbTx) + assert.NoError(t, err) + //require.NoError(t, tx.Commit(ctx)) + + lastBlock, err := testState.GetLastBlock(ctx, dbTx) + assert.NoError(t, err) + assert.Equal(t, uint64(1), lastBlock.BlockNumber) + + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (1)") + + require.NoError(t, err) + addr := common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + virtualBatch := state.VirtualBatch{ + BlockNumber: 1, + BatchNumber: 1, + Coinbase: addr, + SequencerAddr: addr, + TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + } + err = testState.AddVirtualBatch(ctx, &virtualBatch, dbTx) + require.NoError(t, err) + + actualVirtualBatch, err := testState.GetVirtualBatch(ctx, 1, dbTx) + require.NoError(t, err) + require.Equal(t, virtualBatch, *actualVirtualBatch) + require.NoError(t, dbTx.Commit(ctx)) +} diff --git a/state/proof.go b/state/proof.go new file mode 100644 index 0000000000..6c68bae87b --- /dev/null +++ b/state/proof.go @@ -0,0 +1,22 @@ +package state + +import "time" + +// Proof struct +type Proof struct { + BatchNumber uint64 + BatchNumberFinal uint64 + Proof string + InputProver string + ProofID *string + // Prover name, unique identifier across prover reboots. + Prover *string + // ProverID prover process identifier. + ProverID *string + // GeneratingSince holds the timestamp for the moment in which the + // proof generation has started by a prover. Nil if the proof is not + // currently generating. + GeneratingSince *time.Time + CreatedAt time.Time + UpdatedAt time.Time +} diff --git a/state/runtime/executor/client.go b/state/runtime/executor/client.go index 3b3978c2a8..d9da82348c 100644 --- a/state/runtime/executor/client.go +++ b/state/runtime/executor/client.go @@ -2,6 +2,7 @@ package executor import ( "context" + "os/exec" "time" "github.com/0xPolygonHermez/zkevm-node/log" @@ -20,15 +21,34 @@ func NewExecutorClient(ctx context.Context, c Config) (pb.ExecutorServiceClient, grpc.WithBlock(), } const maxWaitSeconds = 120 + const maxRetries = 5 ctx, cancel := context.WithTimeout(ctx, maxWaitSeconds*time.Second) - log.Infof("trying to connect to executor: %v", c.URI) - executorConn, err := grpc.DialContext(ctx, c.URI, opts...) - if err != nil { - log.Fatalf("fail to dial: %v", err) + connectionRetries := 0 + + var executorConn *grpc.ClientConn + var err error + delay := 2 + for connectionRetries < maxRetries { + log.Infof("trying to connect to executor: %v", c.URI) + executorConn, err = grpc.DialContext(ctx, c.URI, opts...) + if err != nil { + log.Infof("Retrying connection to executor #%d", connectionRetries) + time.Sleep(time.Duration(delay) * time.Second) + connectionRetries = connectionRetries + 1 + out, err := exec.Command("docker", []string{"logs", "zkevm-prover"}...).Output() + if err == nil { + log.Infof("Prover logs:\n%s\n", out) + } + } else { + log.Infof("connected to executor") + break + } } - log.Infof("connected to executor") + if connectionRetries == maxRetries { + log.Fatalf("fail to dial: %v", err) + } executorClient := pb.NewExecutorServiceClient(executorConn) return executorClient, executorConn, cancel } diff --git a/state/runtime/executor/errors.go b/state/runtime/executor/errors.go index 8e5c2bd361..0ed116c5c7 100644 --- a/state/runtime/executor/errors.go +++ b/state/runtime/executor/errors.go @@ -2,84 +2,325 @@ package executor import ( "fmt" + "math" "github.com/0xPolygonHermez/zkevm-node/state/runtime" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" ) const ( - // ERROR_UNSPECIFIED indicates the execution ended successfully - ERROR_UNSPECIFIED int32 = iota - // ERROR_NO_ERROR indicates the execution ended successfully - ERROR_NO_ERROR - // ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution - ERROR_OUT_OF_GAS - // ERROR_STACK_OVERFLOW indicates a stack overflow has happened - ERROR_STACK_OVERFLOW - // ERROR_STACK_UNDERFLOW indicates a stack overflow has happened - ERROR_STACK_UNDERFLOW - // ERROR_NOT_ENOUGH_FUNDS indicates there is not enough funds to continue the execution - ERROR_NOT_ENOUGH_FUNDS - // ERROR_INSUFFICIENT_BALANCE indicates there is not enough balance to continue the execution - ERROR_INSUFFICIENT_BALANCE - // ERROR_CODE_NOT_FOUND indicates the code was not found - ERROR_CODE_NOT_FOUND - // ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum - ERROR_MAX_CODE_SIZE_EXCEEDED - // ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses - ERROR_CONTRACT_ADDRESS_COLLISION - // ERROR_DEPTH indicates the maximum call depth has been passed - ERROR_DEPTH - // ERROR_EXECUTION_REVERTED indicates the execution has been reverted - ERROR_EXECUTION_REVERTED - // ERROR_CODE_STORE_OUT_OF_GAS indicates there is not enough gas for the storage - ERROR_CODE_STORE_OUT_OF_GAS - // ERROR_OUT_OF_COUNTERS indicates there is not enough counters to continue the execution - ERROR_OUT_OF_COUNTERS - // ERROR_INVALID_TX indicates the transaction is invalid - ERROR_INVALID_TX - // ERROR_INTRINSIC_INVALID_TX indicates the transaction is failing at the intrinsic checks - ERROR_INTRINSIC_INVALID_TX - // ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed - ERROR_BATCH_DATA_TOO_BIG + // ROM_ERROR_UNSPECIFIED indicates the execution ended successfully + ROM_ERROR_UNSPECIFIED int32 = iota + // ROM_ERROR_NO_ERROR indicates the execution ended successfully + ROM_ERROR_NO_ERROR + // ROM_ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution + ROM_ERROR_OUT_OF_GAS + // ROM_ERROR_STACK_OVERFLOW indicates a stack overflow has happened + ROM_ERROR_STACK_OVERFLOW + // ROM_ERROR_STACK_UNDERFLOW indicates a stack overflow has happened + ROM_ERROR_STACK_UNDERFLOW + // ROM_ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum + ROM_ERROR_MAX_CODE_SIZE_EXCEEDED + // ROM_ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses + ROM_ERROR_CONTRACT_ADDRESS_COLLISION + // ROM_ERROR_EXECUTION_REVERTED indicates the execution has been reverted + ROM_ERROR_EXECUTION_REVERTED + // ROM_ERROR_OUT_OF_COUNTERS_STEP indicates there is not enough step counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_STEP + // ROM_ERROR_OUT_OF_COUNTERS_KECCAK indicates there is not enough keccak counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_KECCAK + // ROM_ERROR_OUT_OF_COUNTERS_BINARY indicates there is not enough binary counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_BINARY + // ROM_ERROR_OUT_OF_COUNTERS_MEM indicates there is not enough memory aligncounters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_MEM + // ROM_ERROR_OUT_OF_COUNTERS_ARITH indicates there is not enough arith counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_ARITH + // ROM_ERROR_OUT_OF_COUNTERS_PADDING indicates there is not enough padding counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_PADDING + // ROM_ERROR_OUT_OF_COUNTERS_POSEIDON indicates there is not enough poseidon counters to continue the execution + ROM_ERROR_OUT_OF_COUNTERS_POSEIDON + // ROM_ERROR_INVALID_JUMP indicates there is an invalid jump opcode + ROM_ERROR_INVALID_JUMP + // ROM_ERROR_INVALID_OPCODE indicates there is an invalid opcode + ROM_ERROR_INVALID_OPCODE + // ROM_ERROR_INVALID_STATIC indicates there is an invalid static call + ROM_ERROR_INVALID_STATIC + // ROM_ERROR_INVALID_BYTECODE_STARTS_EF indicates there is a bytecode starting with 0xEF + ROM_ERROR_INVALID_BYTECODE_STARTS_EF + // ROM_ERROR_INTRINSIC_INVALID_SIGNATURE indicates the transaction is failing at the signature intrinsic check + ROM_ERROR_INTRINSIC_INVALID_SIGNATURE + // ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID indicates the transaction is failing at the chain id intrinsic check + ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID + // ROM_ERROR_INTRINSIC_INVALID_NONCE indicates the transaction is failing at the nonce intrinsic check + ROM_ERROR_INTRINSIC_INVALID_NONCE + // ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT indicates the transaction is failing at the gas limit intrinsic check + ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT + // ROM_ERROR_INTRINSIC_INVALID_BALANCE indicates the transaction is failing at balance intrinsic check + ROM_ERROR_INTRINSIC_INVALID_BALANCE + // ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT indicates the batch is exceeding the batch gas limit + ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT + // ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE indicates the batch is exceeding the batch gas limit + ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE + // ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW indicates the transaction gasLimit*gasPrice > MAX_UINT_256 - 1 + ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW + // ROM_ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed + ROM_ERROR_BATCH_DATA_TOO_BIG + // ROM_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + ROM_ERROR_UNSUPPORTED_FORK_ID + // EXECUTOR_ERROR_UNSPECIFIED indicates the execution ended successfully + EXECUTOR_ERROR_UNSPECIFIED = 0 + // EXECUTOR_ERROR_NO_ERROR indicates there was no error + EXECUTOR_ERROR_NO_ERROR = 1 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK indicates that the keccak counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK = 2 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY indicates that the binary counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY = 3 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM indicates that the memory align counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM = 4 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH indicates that the arith counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH = 5 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING indicates that the padding counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING = 6 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON indicates that the poseidon counter exceeded the maximum + EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON = 7 + // EXECUTOR_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + EXECUTOR_ERROR_UNSUPPORTED_FORK_ID = 8 + // EXECUTOR_ERROR_BALANCE_MISMATCH indicates that there is a balance mismatch error in the ROM + EXECUTOR_ERROR_BALANCE_MISMATCH = 9 + // EXECUTOR_ERROR_FEA2SCALAR indicates that there is a fea2scalar error in the execution + EXECUTOR_ERROR_FEA2SCALAR = 10 + // EXECUTOR_ERROR_TOS32 indicates that there is a TOS32 error in the execution + EXECUTOR_ERROR_TOS32 = 11 ) -// Err returns an instance of error related to the ExecutorError -func Err(errorCode pb.Error) error { +var ( + // ErrUnspecified indicates an unspecified executor error + ErrUnspecified = fmt.Errorf("unspecified executor error") + // ErrUnknown indicates an unknown executor error + ErrUnknown = fmt.Errorf("unknown error") +) + +// RomErr returns an instance of error related to the ExecutorError +func RomErr(errorCode pb.RomError) error { e := int32(errorCode) switch e { - case ERROR_NO_ERROR, ERROR_UNSPECIFIED: + case ROM_ERROR_UNSPECIFIED: + return fmt.Errorf("unspecified ROM error") + case ROM_ERROR_NO_ERROR: return nil - case ERROR_OUT_OF_GAS: + case ROM_ERROR_OUT_OF_GAS: return runtime.ErrOutOfGas - case ERROR_STACK_OVERFLOW: + case ROM_ERROR_STACK_OVERFLOW: return runtime.ErrStackOverflow - case ERROR_STACK_UNDERFLOW: + case ROM_ERROR_STACK_UNDERFLOW: return runtime.ErrStackUnderflow - case ERROR_NOT_ENOUGH_FUNDS: - return runtime.ErrNotEnoughFunds - case ERROR_INSUFFICIENT_BALANCE: - return runtime.ErrInsufficientBalance - case ERROR_CODE_NOT_FOUND: - return runtime.ErrCodeNotFound - case ERROR_MAX_CODE_SIZE_EXCEEDED: + case ROM_ERROR_MAX_CODE_SIZE_EXCEEDED: return runtime.ErrMaxCodeSizeExceeded - case ERROR_CONTRACT_ADDRESS_COLLISION: + case ROM_ERROR_CONTRACT_ADDRESS_COLLISION: return runtime.ErrContractAddressCollision - case ERROR_DEPTH: - return runtime.ErrDepth - case ERROR_EXECUTION_REVERTED: + case ROM_ERROR_EXECUTION_REVERTED: return runtime.ErrExecutionReverted - case ERROR_CODE_STORE_OUT_OF_GAS: - return runtime.ErrCodeStoreOutOfGas - case ERROR_OUT_OF_COUNTERS: - return runtime.ErrOutOfCounters - case ERROR_INVALID_TX: - return runtime.ErrInvalidTransaction - case ERROR_INTRINSIC_INVALID_TX: - return runtime.ErrIntrinsicInvalidTransaction - case ERROR_BATCH_DATA_TOO_BIG: + case ROM_ERROR_OUT_OF_COUNTERS_STEP: + return runtime.ErrOutOfCountersStep + case ROM_ERROR_OUT_OF_COUNTERS_KECCAK: + return runtime.ErrOutOfCountersKeccak + case ROM_ERROR_OUT_OF_COUNTERS_BINARY: + return runtime.ErrOutOfCountersBinary + case ROM_ERROR_OUT_OF_COUNTERS_MEM: + return runtime.ErrOutOfCountersMemory + case ROM_ERROR_OUT_OF_COUNTERS_ARITH: + return runtime.ErrOutOfCountersArith + case ROM_ERROR_OUT_OF_COUNTERS_PADDING: + return runtime.ErrOutOfCountersPadding + case ROM_ERROR_OUT_OF_COUNTERS_POSEIDON: + return runtime.ErrOutOfCountersPoseidon + case ROM_ERROR_INVALID_JUMP: + return runtime.ErrInvalidJump + case ROM_ERROR_INVALID_OPCODE: + return runtime.ErrInvalidOpCode + case ROM_ERROR_INVALID_STATIC: + return runtime.ErrInvalidStatic + case ROM_ERROR_INVALID_BYTECODE_STARTS_EF: + return runtime.ErrInvalidByteCodeStartsEF + case ROM_ERROR_INTRINSIC_INVALID_SIGNATURE: + return runtime.ErrIntrinsicInvalidSignature + case ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID: + return runtime.ErrIntrinsicInvalidChainID + case ROM_ERROR_INTRINSIC_INVALID_NONCE: + return runtime.ErrIntrinsicInvalidNonce + case ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT: + return runtime.ErrIntrinsicInvalidGasLimit + case ROM_ERROR_INTRINSIC_INVALID_BALANCE: + return runtime.ErrIntrinsicInvalidBalance + case ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT: + return runtime.ErrIntrinsicInvalidBatchGasLimit + case ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE: + return runtime.ErrIntrinsicInvalidSenderCode + case ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW: + return runtime.ErrIntrinsicInvalidTxGasOverflow + case ROM_ERROR_BATCH_DATA_TOO_BIG: return runtime.ErrBatchDataTooBig + case ROM_ERROR_UNSUPPORTED_FORK_ID: + return runtime.ErrUnsupportedForkId } return fmt.Errorf("unknown error") } + +// RomErrorCode returns the error code for a given error +func RomErrorCode(err error) pb.RomError { + switch err { + case nil: + return pb.RomError(ROM_ERROR_NO_ERROR) + case runtime.ErrOutOfGas: + return pb.RomError(ROM_ERROR_OUT_OF_GAS) + case runtime.ErrStackOverflow: + return pb.RomError(ROM_ERROR_STACK_OVERFLOW) + case runtime.ErrStackUnderflow: + return pb.RomError(ROM_ERROR_STACK_UNDERFLOW) + case runtime.ErrMaxCodeSizeExceeded: + return pb.RomError(ROM_ERROR_MAX_CODE_SIZE_EXCEEDED) + case runtime.ErrContractAddressCollision: + return pb.RomError(ROM_ERROR_CONTRACT_ADDRESS_COLLISION) + case runtime.ErrExecutionReverted: + return pb.RomError(ROM_ERROR_EXECUTION_REVERTED) + case runtime.ErrOutOfCountersStep: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_STEP) + case runtime.ErrOutOfCountersKeccak: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_KECCAK) + case runtime.ErrOutOfCountersBinary: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_BINARY) + case runtime.ErrOutOfCountersMemory: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_MEM) + case runtime.ErrOutOfCountersArith: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_ARITH) + case runtime.ErrOutOfCountersPadding: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_PADDING) + case runtime.ErrOutOfCountersPoseidon: + return pb.RomError(ROM_ERROR_OUT_OF_COUNTERS_POSEIDON) + case runtime.ErrInvalidJump: + return pb.RomError(ROM_ERROR_INVALID_JUMP) + case runtime.ErrInvalidOpCode: + return pb.RomError(ROM_ERROR_INVALID_OPCODE) + case runtime.ErrInvalidStatic: + return pb.RomError(ROM_ERROR_INVALID_STATIC) + case runtime.ErrInvalidByteCodeStartsEF: + return pb.RomError(ROM_ERROR_INVALID_BYTECODE_STARTS_EF) + case runtime.ErrIntrinsicInvalidSignature: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_SIGNATURE) + case runtime.ErrIntrinsicInvalidChainID: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID) + case runtime.ErrIntrinsicInvalidNonce: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_NONCE) + case runtime.ErrIntrinsicInvalidGasLimit: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT) + case runtime.ErrIntrinsicInvalidBalance: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_BALANCE) + case runtime.ErrIntrinsicInvalidBatchGasLimit: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT) + case runtime.ErrIntrinsicInvalidSenderCode: + return pb.RomError(ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE) + case runtime.ErrIntrinsicInvalidTxGasOverflow: + return pb.RomError(ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW) + case runtime.ErrBatchDataTooBig: + return pb.RomError(ROM_ERROR_BATCH_DATA_TOO_BIG) + case runtime.ErrUnsupportedForkId: + return pb.RomError(ROM_ERROR_UNSUPPORTED_FORK_ID) + } + return math.MaxInt32 +} + +// IsROMOutOfCountersError indicates if the error is an ROM OOC +func IsROMOutOfCountersError(error pb.RomError) bool { + return int32(error) >= ROM_ERROR_OUT_OF_COUNTERS_STEP && int32(error) <= ROM_ERROR_OUT_OF_COUNTERS_POSEIDON +} + +// IsROMOutOfGasError indicates if the error is an ROM OOG +func IsROMOutOfGasError(error pb.RomError) bool { + return int32(error) == ROM_ERROR_OUT_OF_GAS +} + +// IsExecutorOutOfCountersError indicates if the error is an ROM OOC +func IsExecutorOutOfCountersError(error pb.ExecutorError) bool { + return int32(error) >= EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK && int32(error) <= ROM_ERROR_OUT_OF_COUNTERS_POSEIDON +} + +// IsExecutorUnspecifiedError indicates an unspecified error in the executor +func IsExecutorUnspecifiedError(error pb.ExecutorError) bool { + return int32(error) == EXECUTOR_ERROR_UNSPECIFIED +} + +// IsIntrinsicError indicates if the error is due to a intrinsic check +func IsIntrinsicError(error pb.RomError) bool { + return int32(error) >= ROM_ERROR_INTRINSIC_INVALID_SIGNATURE && int32(error) <= ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW +} + +// IsInvalidNonceError indicates if the error is due to a invalid nonce +func IsInvalidNonceError(error pb.RomError) bool { + return int32(error) == ROM_ERROR_INTRINSIC_INVALID_NONCE +} + +// IsInvalidBalanceError indicates if the error is due to a invalid balance +func IsInvalidBalanceError(error pb.RomError) bool { + return int32(error) == ROM_ERROR_INTRINSIC_INVALID_BALANCE +} + +// ExecutorErr returns an instance of error related to the ExecutorError +func ExecutorErr(errorCode pb.ExecutorError) error { + e := int32(errorCode) + switch e { + case EXECUTOR_ERROR_UNSPECIFIED: + return ErrUnspecified + case EXECUTOR_ERROR_NO_ERROR: + return nil + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK: + return runtime.ErrOutOfCountersKeccak + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY: + return runtime.ErrOutOfCountersBinary + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM: + return runtime.ErrOutOfCountersMemory + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH: + return runtime.ErrOutOfCountersArith + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING: + return runtime.ErrOutOfCountersPadding + case EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON: + return runtime.ErrOutOfCountersPoseidon + case EXECUTOR_ERROR_UNSUPPORTED_FORK_ID: + return runtime.ErrUnsupportedForkId + case EXECUTOR_ERROR_BALANCE_MISMATCH: + return runtime.ErrBalanceMismatch + case EXECUTOR_ERROR_FEA2SCALAR: + return runtime.ErrFea2Scalar + case EXECUTOR_ERROR_TOS32: + return runtime.ErrTos32 + } + return ErrUnknown +} + +// ExecutorErrorCode returns the error code for a given error +func ExecutorErrorCode(err error) pb.ExecutorError { + switch err { + case nil: + return pb.ExecutorError(EXECUTOR_ERROR_NO_ERROR) + case runtime.ErrOutOfCountersKeccak: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK) + case runtime.ErrOutOfCountersBinary: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY) + case runtime.ErrOutOfCountersMemory: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM) + case runtime.ErrOutOfCountersArith: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH) + case runtime.ErrOutOfCountersPadding: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING) + case runtime.ErrOutOfCountersPoseidon: + return pb.ExecutorError(EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON) + case runtime.ErrUnsupportedForkId: + return pb.ExecutorError(EXECUTOR_ERROR_UNSUPPORTED_FORK_ID) + case runtime.ErrBalanceMismatch: + return pb.ExecutorError(EXECUTOR_ERROR_BALANCE_MISMATCH) + case runtime.ErrFea2Scalar: + return pb.ExecutorError(EXECUTOR_ERROR_FEA2SCALAR) + case runtime.ErrTos32: + return pb.ExecutorError(EXECUTOR_ERROR_TOS32) + } + return math.MaxInt32 +} diff --git a/state/runtime/executor/pb/executor.pb.go b/state/runtime/executor/pb/executor.pb.go index e1c3d6ab71..85a2facf14 100644 --- a/state/runtime/executor/pb/executor.pb.go +++ b/state/runtime/executor/pb/executor.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.21.6 +// protoc-gen-go v1.29.1 +// protoc v3.21.12 // source: executor.proto package pb @@ -20,136 +20,271 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type Error int32 +type RomError int32 const ( - Error_ERROR_UNSPECIFIED Error = 0 - // ERROR_NO_ERROR indicates the execution ended successfully - Error_ERROR_NO_ERROR Error = 1 - // ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution - Error_ERROR_OUT_OF_GAS Error = 2 - // ERROR_STACK_OVERFLOW indicates a stack overflow has happened - Error_ERROR_STACK_OVERFLOW Error = 3 - // ERROR_STACK_UNDERFLOW indicates a stack overflow has happened - Error_ERROR_STACK_UNDERFLOW Error = 4 - // ERROR_NOT_ENOUGH_FUNDS indicates there is not enough funds to continue the execution - Error_ERROR_NOT_ENOUGH_FUNDS Error = 5 - // ERROR_INSUFFICIENT_BALANCE indicates there is not enough balance to continue the execution - Error_ERROR_INSUFFICIENT_BALANCE Error = 6 - // ERROR_CODE_NOT_FOUND indicates the code was not found - Error_ERROR_CODE_NOT_FOUND Error = 7 - // ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum - Error_ERROR_MAX_CODE_SIZE_EXCEEDED Error = 8 - // ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses - Error_ERROR_CONTRACT_ADDRESS_COLLISION Error = 9 - // ERROR_DEPTH indicates the maximun call depth has been passed - Error_ERROR_DEPTH Error = 10 - // ERROR_EXECUTION_REVERTED indicates the execution has been reverted - Error_ERROR_EXECUTION_REVERTED Error = 11 - // ERROR_CODE_STORE_OUT_OF_GAS indicates there is not enough gas for the storage - Error_ERROR_CODE_STORE_OUT_OF_GAS Error = 12 - // ERROR_OUT_OF_COUNTERS indicates there is not enough counters to continue the execution - Error_ERROR_OUT_OF_COUNTERS Error = 13 - // ERROR_INVALID_TX indicates the transaction is invalid because of invalid jump dest, invalid opcode, invalid deploy - // or invalid static tx - Error_ERROR_INVALID_TX Error = 14 - // ERROR_INTRINSIC_INVALID_TX indicates the transaction is failing at the intrinsic checks - Error_ERROR_INTRINSIC_INVALID_TX Error = 15 - // ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed - Error_ERROR_BATCH_DATA_TOO_BIG Error = 16 + RomError_ROM_ERROR_UNSPECIFIED RomError = 0 + // ROM_ERROR_NO_ERROR indicates the execution ended successfully + RomError_ROM_ERROR_NO_ERROR RomError = 1 + // ROM_ERROR_OUT_OF_GAS indicates there is not enough balance to continue the execution + RomError_ROM_ERROR_OUT_OF_GAS RomError = 2 + // ROM_ERROR_STACK_OVERFLOW indicates a stack overflow has happened + RomError_ROM_ERROR_STACK_OVERFLOW RomError = 3 + // ROM_ERROR_STACK_UNDERFLOW indicates a stack overflow has happened + RomError_ROM_ERROR_STACK_UNDERFLOW RomError = 4 + // ROM_ERROR_MAX_CODE_SIZE_EXCEEDED indicates the code size is beyond the maximum + RomError_ROM_ERROR_MAX_CODE_SIZE_EXCEEDED RomError = 5 + // ROM_ERROR_CONTRACT_ADDRESS_COLLISION there is a collision regarding contract addresses + RomError_ROM_ERROR_CONTRACT_ADDRESS_COLLISION RomError = 6 + // ROM_ERROR_EXECUTION_REVERTED indicates the execution has been reverted + RomError_ROM_ERROR_EXECUTION_REVERTED RomError = 7 + // ROM_ERROR_OUT_OF_COUNTERS_STEP indicates there is not enough step counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_STEP RomError = 8 + // ROM_ERROR_OUT_OF_COUNTERS_KECCAK indicates there is not enough keccak counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_KECCAK RomError = 9 + // ROM_ERROR_OUT_OF_COUNTERS_BINARY indicates there is not enough binary counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_BINARY RomError = 10 + // ROM_ERROR_OUT_OF_COUNTERS_MEM indicates there is not enough memory aligncounters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_MEM RomError = 11 + // ROM_ERROR_OUT_OF_COUNTERS_ARITH indicates there is not enough arith counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_ARITH RomError = 12 + // ROM_ERROR_OUT_OF_COUNTERS_PADDING indicates there is not enough padding counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_PADDING RomError = 13 + // ROM_ERROR_OUT_OF_COUNTERS_POSEIDON indicates there is not enough poseidon counters to continue the execution + RomError_ROM_ERROR_OUT_OF_COUNTERS_POSEIDON RomError = 14 + // ROM_ERROR_INVALID_JUMP indicates there is an invalid jump opcode + RomError_ROM_ERROR_INVALID_JUMP RomError = 15 + // ROM_ERROR_INVALID_OPCODE indicates there is an invalid opcode + RomError_ROM_ERROR_INVALID_OPCODE RomError = 16 + // ROM_ERROR_INVALID_STATIC indicates there is an invalid static call + RomError_ROM_ERROR_INVALID_STATIC RomError = 17 + // ROM_ERROR_INVALID_BYTECODE_STARTS_EF indicates there is a bytecode starting with 0xEF + RomError_ROM_ERROR_INVALID_BYTECODE_STARTS_EF RomError = 18 + // ROM_ERROR_INTRINSIC_INVALID_SIGNATURE indicates the transaction is failing at the signature intrinsic check + RomError_ROM_ERROR_INTRINSIC_INVALID_SIGNATURE RomError = 19 + // ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID indicates the transaction is failing at the chain id intrinsic check + RomError_ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID RomError = 20 + // ROM_ERROR_INTRINSIC_INVALID_NONCE indicates the transaction is failing at the nonce intrinsic check + RomError_ROM_ERROR_INTRINSIC_INVALID_NONCE RomError = 21 + // ROM_ERROR_INTRINSIC_INVALID_GAS indicates the transaction is failing at the gas limit intrinsic check + RomError_ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT RomError = 22 + // ROM_ERROR_INTRINSIC_INVALID_BALANCE indicates the transaction is failing at balance intrinsic check + RomError_ROM_ERROR_INTRINSIC_INVALID_BALANCE RomError = 23 + // ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT indicates the batch is exceeding the batch gas limit + RomError_ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT RomError = 24 + // ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE indicates the transaction sender is invalid + RomError_ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE RomError = 25 + // ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW indicates the transaction gasLimit*gasPrice > MAX_UINT_256 - 1 + RomError_ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW RomError = 26 + // ROM_ERROR_BATCH_DATA_TOO_BIG indicates the batch_l2_data is too big to be processed + RomError_ROM_ERROR_BATCH_DATA_TOO_BIG RomError = 27 + // ROM_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + RomError_ROM_ERROR_UNSUPPORTED_FORK_ID RomError = 28 ) -// Enum value maps for Error. +// Enum value maps for RomError. var ( - Error_name = map[int32]string{ - 0: "ERROR_UNSPECIFIED", - 1: "ERROR_NO_ERROR", - 2: "ERROR_OUT_OF_GAS", - 3: "ERROR_STACK_OVERFLOW", - 4: "ERROR_STACK_UNDERFLOW", - 5: "ERROR_NOT_ENOUGH_FUNDS", - 6: "ERROR_INSUFFICIENT_BALANCE", - 7: "ERROR_CODE_NOT_FOUND", - 8: "ERROR_MAX_CODE_SIZE_EXCEEDED", - 9: "ERROR_CONTRACT_ADDRESS_COLLISION", - 10: "ERROR_DEPTH", - 11: "ERROR_EXECUTION_REVERTED", - 12: "ERROR_CODE_STORE_OUT_OF_GAS", - 13: "ERROR_OUT_OF_COUNTERS", - 14: "ERROR_INVALID_TX", - 15: "ERROR_INTRINSIC_INVALID_TX", - 16: "ERROR_BATCH_DATA_TOO_BIG", - } - Error_value = map[string]int32{ - "ERROR_UNSPECIFIED": 0, - "ERROR_NO_ERROR": 1, - "ERROR_OUT_OF_GAS": 2, - "ERROR_STACK_OVERFLOW": 3, - "ERROR_STACK_UNDERFLOW": 4, - "ERROR_NOT_ENOUGH_FUNDS": 5, - "ERROR_INSUFFICIENT_BALANCE": 6, - "ERROR_CODE_NOT_FOUND": 7, - "ERROR_MAX_CODE_SIZE_EXCEEDED": 8, - "ERROR_CONTRACT_ADDRESS_COLLISION": 9, - "ERROR_DEPTH": 10, - "ERROR_EXECUTION_REVERTED": 11, - "ERROR_CODE_STORE_OUT_OF_GAS": 12, - "ERROR_OUT_OF_COUNTERS": 13, - "ERROR_INVALID_TX": 14, - "ERROR_INTRINSIC_INVALID_TX": 15, - "ERROR_BATCH_DATA_TOO_BIG": 16, + RomError_name = map[int32]string{ + 0: "ROM_ERROR_UNSPECIFIED", + 1: "ROM_ERROR_NO_ERROR", + 2: "ROM_ERROR_OUT_OF_GAS", + 3: "ROM_ERROR_STACK_OVERFLOW", + 4: "ROM_ERROR_STACK_UNDERFLOW", + 5: "ROM_ERROR_MAX_CODE_SIZE_EXCEEDED", + 6: "ROM_ERROR_CONTRACT_ADDRESS_COLLISION", + 7: "ROM_ERROR_EXECUTION_REVERTED", + 8: "ROM_ERROR_OUT_OF_COUNTERS_STEP", + 9: "ROM_ERROR_OUT_OF_COUNTERS_KECCAK", + 10: "ROM_ERROR_OUT_OF_COUNTERS_BINARY", + 11: "ROM_ERROR_OUT_OF_COUNTERS_MEM", + 12: "ROM_ERROR_OUT_OF_COUNTERS_ARITH", + 13: "ROM_ERROR_OUT_OF_COUNTERS_PADDING", + 14: "ROM_ERROR_OUT_OF_COUNTERS_POSEIDON", + 15: "ROM_ERROR_INVALID_JUMP", + 16: "ROM_ERROR_INVALID_OPCODE", + 17: "ROM_ERROR_INVALID_STATIC", + 18: "ROM_ERROR_INVALID_BYTECODE_STARTS_EF", + 19: "ROM_ERROR_INTRINSIC_INVALID_SIGNATURE", + 20: "ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID", + 21: "ROM_ERROR_INTRINSIC_INVALID_NONCE", + 22: "ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT", + 23: "ROM_ERROR_INTRINSIC_INVALID_BALANCE", + 24: "ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT", + 25: "ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE", + 26: "ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW", + 27: "ROM_ERROR_BATCH_DATA_TOO_BIG", + 28: "ROM_ERROR_UNSUPPORTED_FORK_ID", + } + RomError_value = map[string]int32{ + "ROM_ERROR_UNSPECIFIED": 0, + "ROM_ERROR_NO_ERROR": 1, + "ROM_ERROR_OUT_OF_GAS": 2, + "ROM_ERROR_STACK_OVERFLOW": 3, + "ROM_ERROR_STACK_UNDERFLOW": 4, + "ROM_ERROR_MAX_CODE_SIZE_EXCEEDED": 5, + "ROM_ERROR_CONTRACT_ADDRESS_COLLISION": 6, + "ROM_ERROR_EXECUTION_REVERTED": 7, + "ROM_ERROR_OUT_OF_COUNTERS_STEP": 8, + "ROM_ERROR_OUT_OF_COUNTERS_KECCAK": 9, + "ROM_ERROR_OUT_OF_COUNTERS_BINARY": 10, + "ROM_ERROR_OUT_OF_COUNTERS_MEM": 11, + "ROM_ERROR_OUT_OF_COUNTERS_ARITH": 12, + "ROM_ERROR_OUT_OF_COUNTERS_PADDING": 13, + "ROM_ERROR_OUT_OF_COUNTERS_POSEIDON": 14, + "ROM_ERROR_INVALID_JUMP": 15, + "ROM_ERROR_INVALID_OPCODE": 16, + "ROM_ERROR_INVALID_STATIC": 17, + "ROM_ERROR_INVALID_BYTECODE_STARTS_EF": 18, + "ROM_ERROR_INTRINSIC_INVALID_SIGNATURE": 19, + "ROM_ERROR_INTRINSIC_INVALID_CHAIN_ID": 20, + "ROM_ERROR_INTRINSIC_INVALID_NONCE": 21, + "ROM_ERROR_INTRINSIC_INVALID_GAS_LIMIT": 22, + "ROM_ERROR_INTRINSIC_INVALID_BALANCE": 23, + "ROM_ERROR_INTRINSIC_INVALID_BATCH_GAS_LIMIT": 24, + "ROM_ERROR_INTRINSIC_INVALID_SENDER_CODE": 25, + "ROM_ERROR_INTRINSIC_TX_GAS_OVERFLOW": 26, + "ROM_ERROR_BATCH_DATA_TOO_BIG": 27, + "ROM_ERROR_UNSUPPORTED_FORK_ID": 28, } ) -func (x Error) Enum() *Error { - p := new(Error) +func (x RomError) Enum() *RomError { + p := new(RomError) *p = x return p } -func (x Error) String() string { +func (x RomError) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } -func (Error) Descriptor() protoreflect.EnumDescriptor { +func (RomError) Descriptor() protoreflect.EnumDescriptor { return file_executor_proto_enumTypes[0].Descriptor() } -func (Error) Type() protoreflect.EnumType { +func (RomError) Type() protoreflect.EnumType { return &file_executor_proto_enumTypes[0] } -func (x Error) Number() protoreflect.EnumNumber { +func (x RomError) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } -// Deprecated: Use Error.Descriptor instead. -func (Error) EnumDescriptor() ([]byte, []int) { +// Deprecated: Use RomError.Descriptor instead. +func (RomError) EnumDescriptor() ([]byte, []int) { return file_executor_proto_rawDescGZIP(), []int{0} } +type ExecutorError int32 + +const ( + ExecutorError_EXECUTOR_ERROR_UNSPECIFIED ExecutorError = 0 + // EXECUTOR_ERROR_NO_ERROR indicates there was no error + ExecutorError_EXECUTOR_ERROR_NO_ERROR ExecutorError = 1 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK indicates that the keccak counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK ExecutorError = 2 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY indicates that the binary counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY ExecutorError = 3 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM indicates that the memory align counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM ExecutorError = 4 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH indicates that the arith counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH ExecutorError = 5 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING indicates that the padding counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING ExecutorError = 6 + // EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON indicates that the poseidon counter exceeded the maximum + ExecutorError_EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON ExecutorError = 7 + // EXECUTOR_ERROR_UNSUPPORTED_FORK_ID indicates that the fork id is not supported + ExecutorError_EXECUTOR_ERROR_UNSUPPORTED_FORK_ID ExecutorError = 8 + // EXECUTOR_ERROR_BALANCE_MISMATCH indicates that there is a balance mismatch error in the ROM + ExecutorError_EXECUTOR_ERROR_BALANCE_MISMATCH ExecutorError = 9 + // EXECUTOR_ERROR_FEA2SCALAR indicates that there is a fea2scalar error in the execution + ExecutorError_EXECUTOR_ERROR_FEA2SCALAR ExecutorError = 10 + // EXECUTOR_ERROR_TOS32 indicates that there is a TOS32 error in the execution + ExecutorError_EXECUTOR_ERROR_TOS32 ExecutorError = 11 +) + +// Enum value maps for ExecutorError. +var ( + ExecutorError_name = map[int32]string{ + 0: "EXECUTOR_ERROR_UNSPECIFIED", + 1: "EXECUTOR_ERROR_NO_ERROR", + 2: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK", + 3: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY", + 4: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM", + 5: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH", + 6: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING", + 7: "EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON", + 8: "EXECUTOR_ERROR_UNSUPPORTED_FORK_ID", + 9: "EXECUTOR_ERROR_BALANCE_MISMATCH", + 10: "EXECUTOR_ERROR_FEA2SCALAR", + 11: "EXECUTOR_ERROR_TOS32", + } + ExecutorError_value = map[string]int32{ + "EXECUTOR_ERROR_UNSPECIFIED": 0, + "EXECUTOR_ERROR_NO_ERROR": 1, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_KECCAK": 2, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_BINARY": 3, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_MEM": 4, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_ARITH": 5, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_PADDING": 6, + "EXECUTOR_ERROR_COUNTERS_OVERFLOW_POSEIDON": 7, + "EXECUTOR_ERROR_UNSUPPORTED_FORK_ID": 8, + "EXECUTOR_ERROR_BALANCE_MISMATCH": 9, + "EXECUTOR_ERROR_FEA2SCALAR": 10, + "EXECUTOR_ERROR_TOS32": 11, + } +) + +func (x ExecutorError) Enum() *ExecutorError { + p := new(ExecutorError) + *p = x + return p +} + +func (x ExecutorError) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ExecutorError) Descriptor() protoreflect.EnumDescriptor { + return file_executor_proto_enumTypes[1].Descriptor() +} + +func (ExecutorError) Type() protoreflect.EnumType { + return &file_executor_proto_enumTypes[1] +} + +func (x ExecutorError) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ExecutorError.Descriptor instead. +func (ExecutorError) EnumDescriptor() ([]byte, []int) { + return file_executor_proto_rawDescGZIP(), []int{1} +} + type ProcessBatchRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - BatchNum uint64 `protobuf:"varint,1,opt,name=batch_num,json=batchNum,proto3" json:"batch_num,omitempty"` - Coinbase string `protobuf:"bytes,2,opt,name=coinbase,proto3" json:"coinbase,omitempty"` - BatchL2Data []byte `protobuf:"bytes,3,opt,name=batch_l2_data,json=batchL2Data,proto3" json:"batch_l2_data,omitempty"` + OldStateRoot []byte `protobuf:"bytes,1,opt,name=old_state_root,json=oldStateRoot,proto3" json:"old_state_root,omitempty"` + OldAccInputHash []byte `protobuf:"bytes,2,opt,name=old_acc_input_hash,json=oldAccInputHash,proto3" json:"old_acc_input_hash,omitempty"` + OldBatchNum uint64 `protobuf:"varint,3,opt,name=old_batch_num,json=oldBatchNum,proto3" json:"old_batch_num,omitempty"` + ChainId uint64 `protobuf:"varint,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ForkId uint64 `protobuf:"varint,5,opt,name=fork_id,json=forkId,proto3" json:"fork_id,omitempty"` + BatchL2Data []byte `protobuf:"bytes,6,opt,name=batch_l2_data,json=batchL2Data,proto3" json:"batch_l2_data,omitempty"` + GlobalExitRoot []byte `protobuf:"bytes,7,opt,name=global_exit_root,json=globalExitRoot,proto3" json:"global_exit_root,omitempty"` + EthTimestamp uint64 `protobuf:"varint,8,opt,name=eth_timestamp,json=ethTimestamp,proto3" json:"eth_timestamp,omitempty"` + Coinbase string `protobuf:"bytes,9,opt,name=coinbase,proto3" json:"coinbase,omitempty"` + UpdateMerkleTree uint32 `protobuf:"varint,10,opt,name=update_merkle_tree,json=updateMerkleTree,proto3" json:"update_merkle_tree,omitempty"` + // flag to indicate that counters should not be taken into account + NoCounters uint64 `protobuf:"varint,11,opt,name=no_counters,json=noCounters,proto3" json:"no_counters,omitempty"` // from is used for unsigned transactions with sender - From string `protobuf:"bytes,4,opt,name=from,proto3" json:"from,omitempty"` - OldStateRoot []byte `protobuf:"bytes,5,opt,name=old_state_root,json=oldStateRoot,proto3" json:"old_state_root,omitempty"` - GlobalExitRoot []byte `protobuf:"bytes,6,opt,name=global_exit_root,json=globalExitRoot,proto3" json:"global_exit_root,omitempty"` - OldLocalExitRoot []byte `protobuf:"bytes,7,opt,name=old_local_exit_root,json=oldLocalExitRoot,proto3" json:"old_local_exit_root,omitempty"` - EthTimestamp uint64 `protobuf:"varint,8,opt,name=eth_timestamp,json=ethTimestamp,proto3" json:"eth_timestamp,omitempty"` - UpdateMerkleTree uint32 `protobuf:"varint,9,opt,name=update_merkle_tree,json=updateMerkleTree,proto3" json:"update_merkle_tree,omitempty"` - TxHashToGenerateExecuteTrace []byte `protobuf:"bytes,10,opt,name=tx_hash_to_generate_execute_trace,json=txHashToGenerateExecuteTrace,proto3" json:"tx_hash_to_generate_execute_trace,omitempty"` - TxHashToGenerateCallTrace []byte `protobuf:"bytes,11,opt,name=tx_hash_to_generate_call_trace,json=txHashToGenerateCallTrace,proto3" json:"tx_hash_to_generate_call_trace,omitempty"` + From string `protobuf:"bytes,12,opt,name=from,proto3" json:"from,omitempty"` // For testing purposes only - Db map[string]string `protobuf:"bytes,12,rep,name=db,proto3" json:"db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - ContractsBytecode map[string]string `protobuf:"bytes,13,rep,name=contracts_bytecode,json=contractsBytecode,proto3" json:"contracts_bytecode,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production - ChainId uint64 `protobuf:"varint,14,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - NoCounters uint64 `protobuf:"varint,15,opt,name=no_counters,json=noCounters,proto3" json:"no_counters,omitempty"` + Db map[string]string `protobuf:"bytes,13,rep,name=db,proto3" json:"db,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ContractsBytecode map[string]string `protobuf:"bytes,14,rep,name=contracts_bytecode,json=contractsBytecode,proto3" json:"contracts_bytecode,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // For debug/testing purpposes only. Don't fill this on production + TraceConfig *TraceConfig `protobuf:"bytes,15,opt,name=trace_config,json=traceConfig,proto3" json:"trace_config,omitempty"` } func (x *ProcessBatchRequest) Reset() { @@ -184,51 +319,51 @@ func (*ProcessBatchRequest) Descriptor() ([]byte, []int) { return file_executor_proto_rawDescGZIP(), []int{0} } -func (x *ProcessBatchRequest) GetBatchNum() uint64 { +func (x *ProcessBatchRequest) GetOldStateRoot() []byte { if x != nil { - return x.BatchNum + return x.OldStateRoot } - return 0 + return nil } -func (x *ProcessBatchRequest) GetCoinbase() string { +func (x *ProcessBatchRequest) GetOldAccInputHash() []byte { if x != nil { - return x.Coinbase + return x.OldAccInputHash } - return "" + return nil } -func (x *ProcessBatchRequest) GetBatchL2Data() []byte { +func (x *ProcessBatchRequest) GetOldBatchNum() uint64 { if x != nil { - return x.BatchL2Data + return x.OldBatchNum } - return nil + return 0 } -func (x *ProcessBatchRequest) GetFrom() string { +func (x *ProcessBatchRequest) GetChainId() uint64 { if x != nil { - return x.From + return x.ChainId } - return "" + return 0 } -func (x *ProcessBatchRequest) GetOldStateRoot() []byte { +func (x *ProcessBatchRequest) GetForkId() uint64 { if x != nil { - return x.OldStateRoot + return x.ForkId } - return nil + return 0 } -func (x *ProcessBatchRequest) GetGlobalExitRoot() []byte { +func (x *ProcessBatchRequest) GetBatchL2Data() []byte { if x != nil { - return x.GlobalExitRoot + return x.BatchL2Data } return nil } -func (x *ProcessBatchRequest) GetOldLocalExitRoot() []byte { +func (x *ProcessBatchRequest) GetGlobalExitRoot() []byte { if x != nil { - return x.OldLocalExitRoot + return x.GlobalExitRoot } return nil } @@ -240,6 +375,13 @@ func (x *ProcessBatchRequest) GetEthTimestamp() uint64 { return 0 } +func (x *ProcessBatchRequest) GetCoinbase() string { + if x != nil { + return x.Coinbase + } + return "" +} + func (x *ProcessBatchRequest) GetUpdateMerkleTree() uint32 { if x != nil { return x.UpdateMerkleTree @@ -247,18 +389,18 @@ func (x *ProcessBatchRequest) GetUpdateMerkleTree() uint32 { return 0 } -func (x *ProcessBatchRequest) GetTxHashToGenerateExecuteTrace() []byte { +func (x *ProcessBatchRequest) GetNoCounters() uint64 { if x != nil { - return x.TxHashToGenerateExecuteTrace + return x.NoCounters } - return nil + return 0 } -func (x *ProcessBatchRequest) GetTxHashToGenerateCallTrace() []byte { +func (x *ProcessBatchRequest) GetFrom() string { if x != nil { - return x.TxHashToGenerateCallTrace + return x.From } - return nil + return "" } func (x *ProcessBatchRequest) GetDb() map[string]string { @@ -275,18 +417,11 @@ func (x *ProcessBatchRequest) GetContractsBytecode() map[string]string { return nil } -func (x *ProcessBatchRequest) GetChainId() uint64 { +func (x *ProcessBatchRequest) GetTraceConfig() *TraceConfig { if x != nil { - return x.ChainId + return x.TraceConfig } - return 0 -} - -func (x *ProcessBatchRequest) GetNoCounters() uint64 { - if x != nil { - return x.NoCounters - } - return 0 + return nil } type ProcessBatchResponse struct { @@ -294,10 +429,10 @@ type ProcessBatchResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CumulativeGasUsed uint64 `protobuf:"varint,1,opt,name=cumulative_gas_used,json=cumulativeGasUsed,proto3" json:"cumulative_gas_used,omitempty"` - Responses []*ProcessTransactionResponse `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"` - NewStateRoot []byte `protobuf:"bytes,3,opt,name=new_state_root,json=newStateRoot,proto3" json:"new_state_root,omitempty"` - NewLocalExitRoot []byte `protobuf:"bytes,4,opt,name=new_local_exit_root,json=newLocalExitRoot,proto3" json:"new_local_exit_root,omitempty"` + NewStateRoot []byte `protobuf:"bytes,1,opt,name=new_state_root,json=newStateRoot,proto3" json:"new_state_root,omitempty"` + NewAccInputHash []byte `protobuf:"bytes,2,opt,name=new_acc_input_hash,json=newAccInputHash,proto3" json:"new_acc_input_hash,omitempty"` + NewLocalExitRoot []byte `protobuf:"bytes,3,opt,name=new_local_exit_root,json=newLocalExitRoot,proto3" json:"new_local_exit_root,omitempty"` + NewBatchNum uint64 `protobuf:"varint,4,opt,name=new_batch_num,json=newBatchNum,proto3" json:"new_batch_num,omitempty"` CntKeccakHashes uint32 `protobuf:"varint,5,opt,name=cnt_keccak_hashes,json=cntKeccakHashes,proto3" json:"cnt_keccak_hashes,omitempty"` CntPoseidonHashes uint32 `protobuf:"varint,6,opt,name=cnt_poseidon_hashes,json=cntPoseidonHashes,proto3" json:"cnt_poseidon_hashes,omitempty"` CntPoseidonPaddings uint32 `protobuf:"varint,7,opt,name=cnt_poseidon_paddings,json=cntPoseidonPaddings,proto3" json:"cnt_poseidon_paddings,omitempty"` @@ -305,7 +440,10 @@ type ProcessBatchResponse struct { CntArithmetics uint32 `protobuf:"varint,9,opt,name=cnt_arithmetics,json=cntArithmetics,proto3" json:"cnt_arithmetics,omitempty"` CntBinaries uint32 `protobuf:"varint,10,opt,name=cnt_binaries,json=cntBinaries,proto3" json:"cnt_binaries,omitempty"` CntSteps uint32 `protobuf:"varint,11,opt,name=cnt_steps,json=cntSteps,proto3" json:"cnt_steps,omitempty"` - Error Error `protobuf:"varint,12,opt,name=error,proto3,enum=executor.v1.Error" json:"error,omitempty"` + CumulativeGasUsed uint64 `protobuf:"varint,12,opt,name=cumulative_gas_used,json=cumulativeGasUsed,proto3" json:"cumulative_gas_used,omitempty"` + Responses []*ProcessTransactionResponse `protobuf:"bytes,13,rep,name=responses,proto3" json:"responses,omitempty"` + Error ExecutorError `protobuf:"varint,14,opt,name=error,proto3,enum=executor.v1.ExecutorError" json:"error,omitempty"` + ReadWriteAddresses map[string]*InfoReadWrite `protobuf:"bytes,15,rep,name=read_write_addresses,json=readWriteAddresses,proto3" json:"read_write_addresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *ProcessBatchResponse) Reset() { @@ -340,32 +478,32 @@ func (*ProcessBatchResponse) Descriptor() ([]byte, []int) { return file_executor_proto_rawDescGZIP(), []int{1} } -func (x *ProcessBatchResponse) GetCumulativeGasUsed() uint64 { +func (x *ProcessBatchResponse) GetNewStateRoot() []byte { if x != nil { - return x.CumulativeGasUsed + return x.NewStateRoot } - return 0 + return nil } -func (x *ProcessBatchResponse) GetResponses() []*ProcessTransactionResponse { +func (x *ProcessBatchResponse) GetNewAccInputHash() []byte { if x != nil { - return x.Responses + return x.NewAccInputHash } return nil } -func (x *ProcessBatchResponse) GetNewStateRoot() []byte { +func (x *ProcessBatchResponse) GetNewLocalExitRoot() []byte { if x != nil { - return x.NewStateRoot + return x.NewLocalExitRoot } return nil } -func (x *ProcessBatchResponse) GetNewLocalExitRoot() []byte { +func (x *ProcessBatchResponse) GetNewBatchNum() uint64 { if x != nil { - return x.NewLocalExitRoot + return x.NewBatchNum } - return nil + return 0 } func (x *ProcessBatchResponse) GetCntKeccakHashes() uint32 { @@ -417,11 +555,183 @@ func (x *ProcessBatchResponse) GetCntSteps() uint32 { return 0 } -func (x *ProcessBatchResponse) GetError() Error { +func (x *ProcessBatchResponse) GetCumulativeGasUsed() uint64 { + if x != nil { + return x.CumulativeGasUsed + } + return 0 +} + +func (x *ProcessBatchResponse) GetResponses() []*ProcessTransactionResponse { + if x != nil { + return x.Responses + } + return nil +} + +func (x *ProcessBatchResponse) GetError() ExecutorError { if x != nil { return x.Error } - return Error_ERROR_UNSPECIFIED + return ExecutorError_EXECUTOR_ERROR_UNSPECIFIED +} + +func (x *ProcessBatchResponse) GetReadWriteAddresses() map[string]*InfoReadWrite { + if x != nil { + return x.ReadWriteAddresses + } + return nil +} + +// Trace configuration request params +type TraceConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Disables storage (default=false) + DisableStorage uint32 `protobuf:"varint,1,opt,name=disable_storage,json=disableStorage,proto3" json:"disable_storage,omitempty"` + // Disables stack (default=false) + DisableStack uint32 `protobuf:"varint,2,opt,name=disable_stack,json=disableStack,proto3" json:"disable_stack,omitempty"` + // Enables memory (default=false) + EnableMemory uint32 `protobuf:"varint,3,opt,name=enable_memory,json=enableMemory,proto3" json:"enable_memory,omitempty"` + // Enables return data (default=false) + EnableReturnData uint32 `protobuf:"varint,4,opt,name=enable_return_data,json=enableReturnData,proto3" json:"enable_return_data,omitempty"` + // Hash of tx in batch to retrieve the execution trace + TxHashToGenerateExecuteTrace []byte `protobuf:"bytes,5,opt,name=tx_hash_to_generate_execute_trace,json=txHashToGenerateExecuteTrace,proto3" json:"tx_hash_to_generate_execute_trace,omitempty"` + // Hash of tx in batch to retrieve the call trace + TxHashToGenerateCallTrace []byte `protobuf:"bytes,6,opt,name=tx_hash_to_generate_call_trace,json=txHashToGenerateCallTrace,proto3" json:"tx_hash_to_generate_call_trace,omitempty"` +} + +func (x *TraceConfig) Reset() { + *x = TraceConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_executor_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TraceConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TraceConfig) ProtoMessage() {} + +func (x *TraceConfig) ProtoReflect() protoreflect.Message { + mi := &file_executor_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TraceConfig.ProtoReflect.Descriptor instead. +func (*TraceConfig) Descriptor() ([]byte, []int) { + return file_executor_proto_rawDescGZIP(), []int{2} +} + +func (x *TraceConfig) GetDisableStorage() uint32 { + if x != nil { + return x.DisableStorage + } + return 0 +} + +func (x *TraceConfig) GetDisableStack() uint32 { + if x != nil { + return x.DisableStack + } + return 0 +} + +func (x *TraceConfig) GetEnableMemory() uint32 { + if x != nil { + return x.EnableMemory + } + return 0 +} + +func (x *TraceConfig) GetEnableReturnData() uint32 { + if x != nil { + return x.EnableReturnData + } + return 0 +} + +func (x *TraceConfig) GetTxHashToGenerateExecuteTrace() []byte { + if x != nil { + return x.TxHashToGenerateExecuteTrace + } + return nil +} + +func (x *TraceConfig) GetTxHashToGenerateCallTrace() []byte { + if x != nil { + return x.TxHashToGenerateCallTrace + } + return nil +} + +type InfoReadWrite struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // If nonce="" then it has not been set; if set, string is in decimal (base 10) + Nonce string `protobuf:"bytes,1,opt,name=nonce,proto3" json:"nonce,omitempty"` + // If balance="" then it has not been set; if set, string is in decimal (base 10) + Balance string `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` +} + +func (x *InfoReadWrite) Reset() { + *x = InfoReadWrite{} + if protoimpl.UnsafeEnabled { + mi := &file_executor_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InfoReadWrite) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InfoReadWrite) ProtoMessage() {} + +func (x *InfoReadWrite) ProtoReflect() protoreflect.Message { + mi := &file_executor_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InfoReadWrite.ProtoReflect.Descriptor instead. +func (*InfoReadWrite) Descriptor() ([]byte, []int) { + return file_executor_proto_rawDescGZIP(), []int{3} +} + +func (x *InfoReadWrite) GetNonce() string { + if x != nil { + return x.Nonce + } + return "" +} + +func (x *InfoReadWrite) GetBalance() string { + if x != nil { + return x.Balance + } + return "" } type CallTrace struct { @@ -436,7 +746,7 @@ type CallTrace struct { func (x *CallTrace) Reset() { *x = CallTrace{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[2] + mi := &file_executor_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -449,7 +759,7 @@ func (x *CallTrace) String() string { func (*CallTrace) ProtoMessage() {} func (x *CallTrace) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[2] + mi := &file_executor_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -462,7 +772,7 @@ func (x *CallTrace) ProtoReflect() protoreflect.Message { // Deprecated: Use CallTrace.ProtoReflect.Descriptor instead. func (*CallTrace) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{2} + return file_executor_proto_rawDescGZIP(), []int{4} } func (x *CallTrace) GetContext() *TransactionContext { @@ -513,7 +823,7 @@ type TransactionContext struct { func (x *TransactionContext) Reset() { *x = TransactionContext{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[3] + mi := &file_executor_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -526,7 +836,7 @@ func (x *TransactionContext) String() string { func (*TransactionContext) ProtoMessage() {} func (x *TransactionContext) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[3] + mi := &file_executor_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -539,7 +849,7 @@ func (x *TransactionContext) ProtoReflect() protoreflect.Message { // Deprecated: Use TransactionContext.ProtoReflect.Descriptor instead. func (*TransactionContext) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{3} + return file_executor_proto_rawDescGZIP(), []int{5} } func (x *TransactionContext) GetType() string { @@ -653,13 +963,13 @@ type TransactionStep struct { // Contract information Contract *Contract `protobuf:"bytes,11,opt,name=contract,proto3" json:"contract,omitempty"` // Error - Error Error `protobuf:"varint,12,opt,name=error,proto3,enum=executor.v1.Error" json:"error,omitempty"` + Error RomError `protobuf:"varint,12,opt,name=error,proto3,enum=executor.v1.RomError" json:"error,omitempty"` } func (x *TransactionStep) Reset() { *x = TransactionStep{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[4] + mi := &file_executor_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -672,7 +982,7 @@ func (x *TransactionStep) String() string { func (*TransactionStep) ProtoMessage() {} func (x *TransactionStep) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[4] + mi := &file_executor_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -685,7 +995,7 @@ func (x *TransactionStep) ProtoReflect() protoreflect.Message { // Deprecated: Use TransactionStep.ProtoReflect.Descriptor instead. func (*TransactionStep) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{4} + return file_executor_proto_rawDescGZIP(), []int{6} } func (x *TransactionStep) GetStateRoot() []byte { @@ -765,11 +1075,11 @@ func (x *TransactionStep) GetContract() *Contract { return nil } -func (x *TransactionStep) GetError() Error { +func (x *TransactionStep) GetError() RomError { if x != nil { return x.Error } - return Error_ERROR_UNSPECIFIED + return RomError_ROM_ERROR_UNSPECIFIED } type Contract struct { @@ -787,7 +1097,7 @@ type Contract struct { func (x *Contract) Reset() { *x = Contract{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[5] + mi := &file_executor_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -800,7 +1110,7 @@ func (x *Contract) String() string { func (*Contract) ProtoMessage() {} func (x *Contract) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[5] + mi := &file_executor_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -813,7 +1123,7 @@ func (x *Contract) ProtoReflect() protoreflect.Message { // Deprecated: Use Contract.ProtoReflect.Descriptor instead. func (*Contract) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{5} + return file_executor_proto_rawDescGZIP(), []int{7} } func (x *Contract) GetAddress() string { @@ -873,7 +1183,7 @@ type ProcessTransactionResponse struct { // Total gas refunded as result of execution GasRefunded uint64 `protobuf:"varint,7,opt,name=gas_refunded,json=gasRefunded,proto3" json:"gas_refunded,omitempty"` // Any error encountered during the execution - Error Error `protobuf:"varint,8,opt,name=error,proto3,enum=executor.v1.Error" json:"error,omitempty"` + Error RomError `protobuf:"varint,8,opt,name=error,proto3,enum=executor.v1.RomError" json:"error,omitempty"` // New SC Address in case of SC creation CreateAddress string `protobuf:"bytes,9,opt,name=create_address,json=createAddress,proto3" json:"create_address,omitempty"` // State Root @@ -888,7 +1198,7 @@ type ProcessTransactionResponse struct { func (x *ProcessTransactionResponse) Reset() { *x = ProcessTransactionResponse{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[6] + mi := &file_executor_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -901,7 +1211,7 @@ func (x *ProcessTransactionResponse) String() string { func (*ProcessTransactionResponse) ProtoMessage() {} func (x *ProcessTransactionResponse) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[6] + mi := &file_executor_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -914,7 +1224,7 @@ func (x *ProcessTransactionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ProcessTransactionResponse.ProtoReflect.Descriptor instead. func (*ProcessTransactionResponse) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{6} + return file_executor_proto_rawDescGZIP(), []int{8} } func (x *ProcessTransactionResponse) GetTxHash() []byte { @@ -966,11 +1276,11 @@ func (x *ProcessTransactionResponse) GetGasRefunded() uint64 { return 0 } -func (x *ProcessTransactionResponse) GetError() Error { +func (x *ProcessTransactionResponse) GetError() RomError { if x != nil { return x.Error } - return Error_ERROR_UNSPECIFIED + return RomError_ROM_ERROR_UNSPECIFIED } func (x *ProcessTransactionResponse) GetCreateAddress() string { @@ -1034,7 +1344,7 @@ type Log struct { func (x *Log) Reset() { *x = Log{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[7] + mi := &file_executor_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1047,7 +1357,7 @@ func (x *Log) String() string { func (*Log) ProtoMessage() {} func (x *Log) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[7] + mi := &file_executor_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1060,7 +1370,7 @@ func (x *Log) ProtoReflect() protoreflect.Message { // Deprecated: Use Log.ProtoReflect.Descriptor instead. func (*Log) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{7} + return file_executor_proto_rawDescGZIP(), []int{9} } func (x *Log) GetAddress() string { @@ -1147,13 +1457,13 @@ type ExecutionTraceStep struct { // Gas refund GasRefund uint64 `protobuf:"varint,11,opt,name=gas_refund,json=gasRefund,proto3" json:"gas_refund,omitempty"` // Error - Error Error `protobuf:"varint,12,opt,name=error,proto3,enum=executor.v1.Error" json:"error,omitempty"` + Error RomError `protobuf:"varint,12,opt,name=error,proto3,enum=executor.v1.RomError" json:"error,omitempty"` } func (x *ExecutionTraceStep) Reset() { *x = ExecutionTraceStep{} if protoimpl.UnsafeEnabled { - mi := &file_executor_proto_msgTypes[8] + mi := &file_executor_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1166,7 +1476,7 @@ func (x *ExecutionTraceStep) String() string { func (*ExecutionTraceStep) ProtoMessage() {} func (x *ExecutionTraceStep) ProtoReflect() protoreflect.Message { - mi := &file_executor_proto_msgTypes[8] + mi := &file_executor_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1179,7 +1489,7 @@ func (x *ExecutionTraceStep) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutionTraceStep.ProtoReflect.Descriptor instead. func (*ExecutionTraceStep) Descriptor() ([]byte, []int) { - return file_executor_proto_rawDescGZIP(), []int{8} + return file_executor_proto_rawDescGZIP(), []int{10} } func (x *ExecutionTraceStep) GetPc() uint64 { @@ -1259,277 +1569,384 @@ func (x *ExecutionTraceStep) GetGasRefund() uint64 { return 0 } -func (x *ExecutionTraceStep) GetError() Error { +func (x *ExecutionTraceStep) GetError() RomError { if x != nil { return x.Error } - return Error_ERROR_UNSPECIFIED + return RomError_ROM_ERROR_UNSPECIFIED } var File_executor_proto protoreflect.FileDescriptor var file_executor_proto_rawDesc = []byte{ 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x22, 0xbf, 0x06, + 0x12, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x22, 0x8e, 0x06, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, - 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, - 0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x12, 0x22, - 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x32, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x32, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, - 0x6f, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x28, 0x0a, 0x10, - 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, - 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x6f, 0x6c, 0x64, 0x5f, 0x6c, 0x6f, - 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6f, 0x6c, 0x64, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, - 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x65, 0x74, - 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, - 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x47, 0x0a, 0x21, 0x74, 0x78, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x1c, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x54, 0x6f, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x12, 0x41, 0x0a, 0x1e, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x5f, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x19, 0x74, 0x78, 0x48, 0x61, 0x73, - 0x68, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x28, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x02, 0x64, 0x62, 0x12, 0x66, - 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, - 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6e, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x1a, 0x35, 0x0a, 0x07, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xab, 0x04, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x75, 0x6d, 0x75, - 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x45, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, - 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, 0x77, 0x5f, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x63, 0x63, - 0x61, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0f, 0x63, 0x6e, 0x74, 0x4b, 0x65, 0x63, 0x63, 0x61, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, - 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x63, - 0x6e, 0x74, 0x50, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, - 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x13, 0x63, 0x6e, 0x74, 0x50, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, 0x50, 0x61, 0x64, 0x64, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, - 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x6e, - 0x74, 0x4d, 0x65, 0x6d, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6e, - 0x74, 0x5f, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x6e, 0x74, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, - 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6e, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6e, 0x74, 0x42, 0x69, - 0x6e, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6e, 0x74, 0x5f, 0x73, 0x74, - 0x65, 0x70, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x63, 0x6e, 0x74, 0x53, 0x74, - 0x65, 0x70, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7a, 0x0a, - 0x09, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x22, 0xbb, 0x02, 0x0a, 0x12, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, - 0x67, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6f, 0x6c, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xde, 0x02, 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6f, + 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x12, 0x6f, + 0x6c, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6f, 0x6c, 0x64, 0x41, 0x63, 0x63, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6c, 0x64, 0x5f, + 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x6f, 0x6c, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x12, 0x19, 0x0a, 0x08, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6b, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6b, 0x49, 0x64, + 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6c, 0x32, 0x5f, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x32, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, + 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, + 0x0a, 0x0d, 0x65, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x65, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x12, + 0x2c, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x72, 0x6b, 0x6c, 0x65, + 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4d, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0a, 0x6e, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, + 0x6f, 0x6d, 0x12, 0x38, 0x0a, 0x02, 0x64, 0x62, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x02, 0x64, 0x62, 0x12, 0x66, 0x0a, 0x12, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3b, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x1a, 0x35, 0x0a, 0x07, 0x44, 0x62, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x73, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd4, + 0x06, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, - 0x70, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x12, 0x0e, 0x0a, 0x02, 0x70, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x70, 0x63, - 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, - 0x61, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x67, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x09, 0x67, 0x61, 0x73, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, - 0x6f, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, - 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x08, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x28, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x78, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, - 0x61, 0x73, 0x22, 0xf3, 0x03, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x6c, - 0x70, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x72, 0x6c, 0x70, 0x54, - 0x78, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x65, 0x74, - 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, - 0x6c, 0x65, 0x66, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x4c, - 0x65, 0x66, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x21, - 0x0a, 0x0c, 0x67, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x61, 0x73, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, - 0x64, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x12, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x24, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, - 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x65, - 0x70, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x12, 0x35, 0x0a, 0x0a, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x09, 0x63, - 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, - 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, - 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, - 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, - 0x0a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x22, 0xc7, 0x03, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x70, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x70, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x70, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, - 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x47, 0x61, 0x73, 0x12, 0x19, - 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x07, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, - 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x53, 0x69, - 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x75, - 0x72, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x07, 0x73, 0x74, 0x6f, - 0x72, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x65, 0x70, 0x2e, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x61, 0x73, 0x5f, 0x72, - 0x65, 0x66, 0x75, 0x6e, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x67, 0x61, 0x73, - 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x1a, 0x3a, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0xda, 0x03, 0x0a, - 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, - 0x0e, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x01, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, - 0x46, 0x5f, 0x47, 0x41, 0x53, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x10, - 0x03, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, - 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x10, 0x04, 0x12, 0x1a, 0x0a, 0x16, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x4e, 0x4f, 0x55, 0x47, 0x48, - 0x5f, 0x46, 0x55, 0x4e, 0x44, 0x53, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, - 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, - 0x10, 0x07, 0x12, 0x20, 0x0a, 0x1c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4d, 0x41, 0x58, 0x5f, - 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x5f, 0x45, 0x58, 0x43, 0x45, 0x45, 0x44, - 0x45, 0x44, 0x10, 0x08, 0x12, 0x24, 0x0a, 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, - 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x43, - 0x4f, 0x4c, 0x4c, 0x49, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x5f, 0x44, 0x45, 0x50, 0x54, 0x48, 0x10, 0x0a, 0x12, 0x1c, 0x0a, 0x18, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, - 0x45, 0x56, 0x45, 0x52, 0x54, 0x45, 0x44, 0x10, 0x0b, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x5f, 0x4f, 0x55, - 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x47, 0x41, 0x53, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, - 0x45, 0x52, 0x53, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x0e, 0x12, 0x1e, 0x0a, 0x1a, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x54, 0x58, 0x10, 0x0f, 0x12, 0x1c, 0x0a, 0x18, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, - 0x54, 0x4f, 0x4f, 0x5f, 0x42, 0x49, 0x47, 0x10, 0x10, 0x32, 0x68, 0x0a, 0x0f, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x0c, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x20, 0x2e, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x0c, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, + 0x12, 0x6e, 0x65, 0x77, 0x5f, 0x61, 0x63, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x41, 0x63, + 0x63, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, + 0x77, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x65, 0x77, + 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, + 0x11, 0x63, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x63, 0x63, 0x61, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x63, 0x6e, 0x74, 0x4b, 0x65, 0x63, + 0x63, 0x61, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6e, 0x74, + 0x5f, 0x70, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x63, 0x6e, 0x74, 0x50, 0x6f, 0x73, 0x65, 0x69, + 0x64, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6e, 0x74, + 0x5f, 0x70, 0x6f, 0x73, 0x65, 0x69, 0x64, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, + 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x63, 0x6e, 0x74, 0x50, 0x6f, 0x73, + 0x65, 0x69, 0x64, 0x6f, 0x6e, 0x50, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x24, 0x0a, + 0x0e, 0x63, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x6e, 0x74, 0x4d, 0x65, 0x6d, 0x41, 0x6c, 0x69, + 0x67, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x65, 0x74, 0x69, 0x63, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x6e, + 0x74, 0x41, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6e, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6e, 0x74, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x08, 0x63, 0x6e, 0x74, 0x53, 0x74, 0x65, 0x70, 0x73, 0x12, 0x2e, 0x0a, 0x13, + 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, + 0x73, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x63, 0x75, 0x6d, 0x75, 0x6c, + 0x61, 0x74, 0x69, 0x76, 0x65, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x45, 0x0a, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x6b, 0x0a, 0x14, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x77, 0x72, + 0x69, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0f, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, + 0x72, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x17, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xba, 0x02, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, + 0x61, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x21, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x1c, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, + 0x41, 0x0a, 0x1e, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x19, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x54, + 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x22, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x22, 0x7a, 0x0a, 0x09, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x65, + 0x12, 0x39, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x73, + 0x74, 0x65, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x22, + 0xbb, 0x02, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, + 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, + 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x03, 0x67, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, + 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, + 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x6c, 0x64, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0c, 0x6f, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xe1, 0x02, + 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x65, + 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x0e, 0x0a, 0x02, 0x70, 0x63, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x02, 0x70, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, + 0x63, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x43, + 0x6f, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x6e, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x67, 0x61, 0x73, 0x52, 0x65, 0x66, 0x75, + 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, + 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, + 0x61, 0x12, 0x31, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0x78, 0x0a, 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x67, 0x61, 0x73, 0x22, 0xf6, 0x03, 0x0a, 0x1a, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x6c, 0x70, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x72, 0x6c, 0x70, 0x54, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x19, 0x0a, 0x08, + 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, + 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x61, 0x73, 0x5f, 0x72, + 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, + 0x61, 0x73, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x24, 0x0a, + 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, + 0x6f, 0x67, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x0e, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x35, 0x0a, + 0x0a, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x19, + 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x74, + 0x63, 0x68, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xca, + 0x03, 0x0a, 0x12, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x63, + 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x70, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x02, 0x70, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, + 0x6e, 0x67, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x72, 0x65, + 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x47, 0x61, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, + 0x73, 0x5f, 0x63, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, + 0x73, 0x43, 0x6f, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x0a, + 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, + 0x61, 0x63, 0x65, 0x53, 0x74, 0x65, 0x70, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x66, 0x75, 0x6e, + 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x67, 0x61, 0x73, 0x52, 0x65, 0x66, 0x75, + 0x6e, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x15, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, + 0x3a, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0xab, 0x08, 0x0a, 0x08, + 0x52, 0x6f, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x4d, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x5f, 0x4e, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, + 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, + 0x47, 0x41, 0x53, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, + 0x57, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, + 0x10, 0x04, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x4d, 0x41, 0x58, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x5f, 0x45, 0x58, + 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x05, 0x12, 0x28, 0x0a, 0x24, 0x52, 0x4f, 0x4d, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x41, 0x43, 0x54, 0x5f, 0x41, + 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x4c, 0x4c, 0x49, 0x53, 0x49, 0x4f, 0x4e, + 0x10, 0x06, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x56, 0x45, 0x52, 0x54, + 0x45, 0x44, 0x10, 0x07, 0x12, 0x22, 0x0a, 0x1e, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, + 0x53, 0x5f, 0x53, 0x54, 0x45, 0x50, 0x10, 0x08, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x4f, 0x4d, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, + 0x4e, 0x54, 0x45, 0x52, 0x53, 0x5f, 0x4b, 0x45, 0x43, 0x43, 0x41, 0x4b, 0x10, 0x09, 0x12, 0x24, + 0x0a, 0x20, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, + 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, 0x5f, 0x42, 0x49, 0x4e, 0x41, + 0x52, 0x59, 0x10, 0x0a, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, + 0x53, 0x5f, 0x4d, 0x45, 0x4d, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x4f, 0x4d, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, + 0x54, 0x45, 0x52, 0x53, 0x5f, 0x41, 0x52, 0x49, 0x54, 0x48, 0x10, 0x0c, 0x12, 0x25, 0x0a, 0x21, + 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, + 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, 0x5f, 0x50, 0x41, 0x44, 0x44, 0x49, 0x4e, + 0x47, 0x10, 0x0d, 0x12, 0x26, 0x0a, 0x22, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, + 0x5f, 0x50, 0x4f, 0x53, 0x45, 0x49, 0x44, 0x4f, 0x4e, 0x10, 0x0e, 0x12, 0x1a, 0x0a, 0x16, 0x52, + 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x5f, 0x4a, 0x55, 0x4d, 0x50, 0x10, 0x0f, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x4d, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x50, 0x43, + 0x4f, 0x44, 0x45, 0x10, 0x10, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49, + 0x43, 0x10, 0x11, 0x12, 0x28, 0x0a, 0x24, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x43, 0x4f, 0x44, + 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x53, 0x5f, 0x45, 0x46, 0x10, 0x12, 0x12, 0x29, 0x0a, + 0x25, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, + 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x49, 0x47, + 0x4e, 0x41, 0x54, 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x28, 0x0a, 0x24, 0x52, 0x4f, 0x4d, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, 0x49, 0x43, 0x5f, + 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x49, 0x44, + 0x10, 0x14, 0x12, 0x25, 0x0a, 0x21, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, + 0x44, 0x5f, 0x4e, 0x4f, 0x4e, 0x43, 0x45, 0x10, 0x15, 0x12, 0x29, 0x0a, 0x25, 0x52, 0x4f, 0x4d, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, 0x49, 0x43, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x47, 0x41, 0x53, 0x5f, 0x4c, 0x49, 0x4d, + 0x49, 0x54, 0x10, 0x16, 0x12, 0x27, 0x0a, 0x23, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, 0x4e, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x17, 0x12, 0x2f, 0x0a, + 0x2b, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, + 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x42, 0x41, 0x54, + 0x43, 0x48, 0x5f, 0x47, 0x41, 0x53, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x18, 0x12, 0x2b, + 0x0a, 0x27, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, + 0x49, 0x4e, 0x53, 0x49, 0x43, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x45, + 0x4e, 0x44, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x19, 0x12, 0x27, 0x0a, 0x23, 0x52, + 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x49, 0x4e, 0x54, 0x52, 0x49, 0x4e, 0x53, + 0x49, 0x43, 0x5f, 0x54, 0x58, 0x5f, 0x47, 0x41, 0x53, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, + 0x4f, 0x57, 0x10, 0x1a, 0x12, 0x20, 0x0a, 0x1c, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x54, 0x4f, 0x4f, + 0x5f, 0x42, 0x49, 0x47, 0x10, 0x1b, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x4f, 0x4d, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x5f, + 0x46, 0x4f, 0x52, 0x4b, 0x5f, 0x49, 0x44, 0x10, 0x1c, 0x2a, 0xdf, 0x03, 0x0a, 0x0d, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1e, 0x0a, 0x1a, 0x45, + 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x45, + 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x45, 0x58, 0x45, 0x43, + 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, + 0x45, 0x52, 0x53, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x4b, 0x45, 0x43, + 0x43, 0x41, 0x4b, 0x10, 0x02, 0x12, 0x2b, 0x0a, 0x27, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, + 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, + 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, + 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, 0x5f, 0x4f, 0x56, + 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x4d, 0x45, 0x4d, 0x10, 0x04, 0x12, 0x2a, 0x0a, 0x26, + 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, + 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x53, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, + 0x5f, 0x41, 0x52, 0x49, 0x54, 0x48, 0x10, 0x05, 0x12, 0x2c, 0x0a, 0x28, 0x45, 0x58, 0x45, 0x43, + 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, + 0x45, 0x52, 0x53, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x50, 0x41, 0x44, + 0x44, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x2d, 0x0a, 0x29, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, + 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, + 0x53, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x50, 0x4f, 0x53, 0x45, 0x49, + 0x44, 0x4f, 0x4e, 0x10, 0x07, 0x12, 0x26, 0x0a, 0x22, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, + 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, + 0x54, 0x45, 0x44, 0x5f, 0x46, 0x4f, 0x52, 0x4b, 0x5f, 0x49, 0x44, 0x10, 0x08, 0x12, 0x23, 0x0a, + 0x1f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, + 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x4d, 0x41, 0x54, 0x43, 0x48, + 0x10, 0x09, 0x12, 0x1d, 0x0a, 0x19, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x46, 0x45, 0x41, 0x32, 0x53, 0x43, 0x41, 0x4c, 0x41, 0x52, 0x10, + 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x4f, 0x52, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x54, 0x4f, 0x53, 0x33, 0x32, 0x10, 0x0b, 0x32, 0x68, 0x0a, 0x0f, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x55, + 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x20, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, - 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x21, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, + 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1544,45 +1961,52 @@ func file_executor_proto_rawDescGZIP() []byte { return file_executor_proto_rawDescData } -var file_executor_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_executor_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_executor_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_executor_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_executor_proto_goTypes = []interface{}{ - (Error)(0), // 0: executor.v1.Error - (*ProcessBatchRequest)(nil), // 1: executor.v1.ProcessBatchRequest - (*ProcessBatchResponse)(nil), // 2: executor.v1.ProcessBatchResponse - (*CallTrace)(nil), // 3: executor.v1.CallTrace - (*TransactionContext)(nil), // 4: executor.v1.TransactionContext - (*TransactionStep)(nil), // 5: executor.v1.TransactionStep - (*Contract)(nil), // 6: executor.v1.Contract - (*ProcessTransactionResponse)(nil), // 7: executor.v1.ProcessTransactionResponse - (*Log)(nil), // 8: executor.v1.Log - (*ExecutionTraceStep)(nil), // 9: executor.v1.ExecutionTraceStep - nil, // 10: executor.v1.ProcessBatchRequest.DbEntry - nil, // 11: executor.v1.ProcessBatchRequest.ContractsBytecodeEntry - nil, // 12: executor.v1.ExecutionTraceStep.StorageEntry + (RomError)(0), // 0: executor.v1.RomError + (ExecutorError)(0), // 1: executor.v1.ExecutorError + (*ProcessBatchRequest)(nil), // 2: executor.v1.ProcessBatchRequest + (*ProcessBatchResponse)(nil), // 3: executor.v1.ProcessBatchResponse + (*TraceConfig)(nil), // 4: executor.v1.TraceConfig + (*InfoReadWrite)(nil), // 5: executor.v1.InfoReadWrite + (*CallTrace)(nil), // 6: executor.v1.CallTrace + (*TransactionContext)(nil), // 7: executor.v1.TransactionContext + (*TransactionStep)(nil), // 8: executor.v1.TransactionStep + (*Contract)(nil), // 9: executor.v1.Contract + (*ProcessTransactionResponse)(nil), // 10: executor.v1.ProcessTransactionResponse + (*Log)(nil), // 11: executor.v1.Log + (*ExecutionTraceStep)(nil), // 12: executor.v1.ExecutionTraceStep + nil, // 13: executor.v1.ProcessBatchRequest.DbEntry + nil, // 14: executor.v1.ProcessBatchRequest.ContractsBytecodeEntry + nil, // 15: executor.v1.ProcessBatchResponse.ReadWriteAddressesEntry + nil, // 16: executor.v1.ExecutionTraceStep.StorageEntry } var file_executor_proto_depIdxs = []int32{ - 10, // 0: executor.v1.ProcessBatchRequest.db:type_name -> executor.v1.ProcessBatchRequest.DbEntry - 11, // 1: executor.v1.ProcessBatchRequest.contracts_bytecode:type_name -> executor.v1.ProcessBatchRequest.ContractsBytecodeEntry - 7, // 2: executor.v1.ProcessBatchResponse.responses:type_name -> executor.v1.ProcessTransactionResponse - 0, // 3: executor.v1.ProcessBatchResponse.error:type_name -> executor.v1.Error - 4, // 4: executor.v1.CallTrace.context:type_name -> executor.v1.TransactionContext - 5, // 5: executor.v1.CallTrace.steps:type_name -> executor.v1.TransactionStep - 6, // 6: executor.v1.TransactionStep.contract:type_name -> executor.v1.Contract - 0, // 7: executor.v1.TransactionStep.error:type_name -> executor.v1.Error - 0, // 8: executor.v1.ProcessTransactionResponse.error:type_name -> executor.v1.Error - 8, // 9: executor.v1.ProcessTransactionResponse.logs:type_name -> executor.v1.Log - 9, // 10: executor.v1.ProcessTransactionResponse.execution_trace:type_name -> executor.v1.ExecutionTraceStep - 3, // 11: executor.v1.ProcessTransactionResponse.call_trace:type_name -> executor.v1.CallTrace - 12, // 12: executor.v1.ExecutionTraceStep.storage:type_name -> executor.v1.ExecutionTraceStep.StorageEntry - 0, // 13: executor.v1.ExecutionTraceStep.error:type_name -> executor.v1.Error - 1, // 14: executor.v1.ExecutorService.ProcessBatch:input_type -> executor.v1.ProcessBatchRequest - 2, // 15: executor.v1.ExecutorService.ProcessBatch:output_type -> executor.v1.ProcessBatchResponse - 15, // [15:16] is the sub-list for method output_type - 14, // [14:15] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 13, // 0: executor.v1.ProcessBatchRequest.db:type_name -> executor.v1.ProcessBatchRequest.DbEntry + 14, // 1: executor.v1.ProcessBatchRequest.contracts_bytecode:type_name -> executor.v1.ProcessBatchRequest.ContractsBytecodeEntry + 4, // 2: executor.v1.ProcessBatchRequest.trace_config:type_name -> executor.v1.TraceConfig + 10, // 3: executor.v1.ProcessBatchResponse.responses:type_name -> executor.v1.ProcessTransactionResponse + 1, // 4: executor.v1.ProcessBatchResponse.error:type_name -> executor.v1.ExecutorError + 15, // 5: executor.v1.ProcessBatchResponse.read_write_addresses:type_name -> executor.v1.ProcessBatchResponse.ReadWriteAddressesEntry + 7, // 6: executor.v1.CallTrace.context:type_name -> executor.v1.TransactionContext + 8, // 7: executor.v1.CallTrace.steps:type_name -> executor.v1.TransactionStep + 9, // 8: executor.v1.TransactionStep.contract:type_name -> executor.v1.Contract + 0, // 9: executor.v1.TransactionStep.error:type_name -> executor.v1.RomError + 0, // 10: executor.v1.ProcessTransactionResponse.error:type_name -> executor.v1.RomError + 11, // 11: executor.v1.ProcessTransactionResponse.logs:type_name -> executor.v1.Log + 12, // 12: executor.v1.ProcessTransactionResponse.execution_trace:type_name -> executor.v1.ExecutionTraceStep + 6, // 13: executor.v1.ProcessTransactionResponse.call_trace:type_name -> executor.v1.CallTrace + 16, // 14: executor.v1.ExecutionTraceStep.storage:type_name -> executor.v1.ExecutionTraceStep.StorageEntry + 0, // 15: executor.v1.ExecutionTraceStep.error:type_name -> executor.v1.RomError + 5, // 16: executor.v1.ProcessBatchResponse.ReadWriteAddressesEntry.value:type_name -> executor.v1.InfoReadWrite + 2, // 17: executor.v1.ExecutorService.ProcessBatch:input_type -> executor.v1.ProcessBatchRequest + 3, // 18: executor.v1.ExecutorService.ProcessBatch:output_type -> executor.v1.ProcessBatchResponse + 18, // [18:19] is the sub-list for method output_type + 17, // [17:18] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_executor_proto_init() } @@ -1616,7 +2040,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CallTrace); i { + switch v := v.(*TraceConfig); i { case 0: return &v.state case 1: @@ -1628,7 +2052,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionContext); i { + switch v := v.(*InfoReadWrite); i { case 0: return &v.state case 1: @@ -1640,7 +2064,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TransactionStep); i { + switch v := v.(*CallTrace); i { case 0: return &v.state case 1: @@ -1652,7 +2076,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Contract); i { + switch v := v.(*TransactionContext); i { case 0: return &v.state case 1: @@ -1664,7 +2088,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProcessTransactionResponse); i { + switch v := v.(*TransactionStep); i { case 0: return &v.state case 1: @@ -1676,7 +2100,7 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Log); i { + switch v := v.(*Contract); i { case 0: return &v.state case 1: @@ -1688,6 +2112,30 @@ func file_executor_proto_init() { } } file_executor_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProcessTransactionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_executor_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Log); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_executor_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionTraceStep); i { case 0: return &v.state @@ -1705,8 +2153,8 @@ func file_executor_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_executor_proto_rawDesc, - NumEnums: 1, - NumMessages: 12, + NumEnums: 2, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/state/runtime/executor/pb/executor_grpc.pb.go b/state/runtime/executor/pb/executor_grpc.pb.go index d48676e2a0..78b00bd149 100644 --- a/state/runtime/executor/pb/executor_grpc.pb.go +++ b/state/runtime/executor/pb/executor_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.6 +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 // source: executor.proto package pb @@ -18,11 +18,15 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + ExecutorService_ProcessBatch_FullMethodName = "/executor.v1.ExecutorService/ProcessBatch" +) + // ExecutorServiceClient is the client API for ExecutorService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ExecutorServiceClient interface { - /// Processes a batch + // / Processes a batch ProcessBatch(ctx context.Context, in *ProcessBatchRequest, opts ...grpc.CallOption) (*ProcessBatchResponse, error) } @@ -36,7 +40,7 @@ func NewExecutorServiceClient(cc grpc.ClientConnInterface) ExecutorServiceClient func (c *executorServiceClient) ProcessBatch(ctx context.Context, in *ProcessBatchRequest, opts ...grpc.CallOption) (*ProcessBatchResponse, error) { out := new(ProcessBatchResponse) - err := c.cc.Invoke(ctx, "/executor.v1.ExecutorService/ProcessBatch", in, out, opts...) + err := c.cc.Invoke(ctx, ExecutorService_ProcessBatch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -47,7 +51,7 @@ func (c *executorServiceClient) ProcessBatch(ctx context.Context, in *ProcessBat // All implementations must embed UnimplementedExecutorServiceServer // for forward compatibility type ExecutorServiceServer interface { - /// Processes a batch + // / Processes a batch ProcessBatch(context.Context, *ProcessBatchRequest) (*ProcessBatchResponse, error) mustEmbedUnimplementedExecutorServiceServer() } @@ -82,7 +86,7 @@ func _ExecutorService_ProcessBatch_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/executor.v1.ExecutorService/ProcessBatch", + FullMethod: ExecutorService_ProcessBatch_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ExecutorServiceServer).ProcessBatch(ctx, req.(*ProcessBatchRequest)) diff --git a/state/runtime/fakevm/analysis.go b/state/runtime/fakevm/analysis.go new file mode 100644 index 0000000000..3b6d81fad2 --- /dev/null +++ b/state/runtime/fakevm/analysis.go @@ -0,0 +1,118 @@ +// Copyright 2014 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 fakevm + +const ( + set2BitsMask = uint16(0b11) + set3BitsMask = uint16(0b111) + set4BitsMask = uint16(0b1111) + set5BitsMask = uint16(0b1_1111) + set6BitsMask = uint16(0b11_1111) + set7BitsMask = uint16(0b111_1111) +) + +// bitvec is a bit vector which maps bytes in a program. +// An unset bit means the byte is an opcode, a set bit means +// it's data (i.e. argument of PUSHxx). +type bitvec []byte + +func (bits bitvec) set1(pos uint64) { + bits[pos/8] |= 1 << (pos % 8) +} + +func (bits bitvec) setN(flag uint16, pos uint64) { + a := flag << (pos % 8) + bits[pos/8] |= byte(a) + if b := byte(a >> 8); b != 0 { + bits[pos/8+1] = b + } +} + +func (bits bitvec) set8(pos uint64) { + a := byte(0xFF << (pos % 8)) + bits[pos/8] |= a + bits[pos/8+1] = ^a +} + +func (bits bitvec) set16(pos uint64) { + a := byte(0xFF << (pos % 8)) + bits[pos/8] |= a + bits[pos/8+1] = 0xFF + bits[pos/8+2] = ^a +} + +// codeSegment checks if the position is in a code segment. +func (bits *bitvec) codeSegment(pos uint64) bool { + return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0 +} + +// codeBitmap collects data locations in code. +func codeBitmap(code []byte) bitvec { + // The bitmap is 4 bytes longer than necessary, in case the code + // ends with a PUSH32, the algorithm will push zeroes onto the + // bitvector outside the bounds of the actual code. + bits := make(bitvec, len(code)/8+1+4) + return codeBitmapInternal(code, bits) +} + +// codeBitmapInternal is the internal implementation of codeBitmap. +// It exists for the purpose of being able to run benchmark tests +// without dynamic allocations affecting the results. +func codeBitmapInternal(code, bits bitvec) bitvec { + for pc := uint64(0); pc < uint64(len(code)); { + op := OpCode(code[pc]) + pc++ + if int8(op) < int8(PUSH1) { // If not PUSH (the int8(op) > int(PUSH32) is always false). + continue + } + numbits := op - PUSH1 + 1 + if numbits >= 8 { + for ; numbits >= 16; numbits -= 16 { + bits.set16(pc) + pc += 16 + } + for ; numbits >= 8; numbits -= 8 { + bits.set8(pc) + pc += 8 + } + } + switch numbits { + case 1: + bits.set1(pc) + pc += 1 + case 2: + bits.setN(set2BitsMask, pc) + pc += 2 + case 3: + bits.setN(set3BitsMask, pc) + pc += 3 + case 4: + bits.setN(set4BitsMask, pc) + pc += 4 + case 5: + bits.setN(set5BitsMask, pc) + pc += 5 + case 6: + bits.setN(set6BitsMask, pc) + pc += 6 + case 7: + bits.setN(set7BitsMask, pc) + pc += 7 + } + } + return bits +} diff --git a/state/runtime/fakevm/common.go b/state/runtime/fakevm/common.go new file mode 100644 index 0000000000..c637c7fdd0 --- /dev/null +++ b/state/runtime/fakevm/common.go @@ -0,0 +1,82 @@ +// Copyright 2014 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 fakevm + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/holiman/uint256" +) + +// calcMemSize64 calculates the required memory size, and returns +// the size and whether the result overflowed uint64 +func calcMemSize64(off, l *uint256.Int) (uint64, bool) { + if !l.IsUint64() { + return 0, true + } + return calcMemSize64WithUint(off, l.Uint64()) +} + +// calcMemSize64WithUint calculates the required memory size, and returns +// the size and whether the result overflowed uint64 +// Identical to calcMemSize64, but length is a uint64 +func calcMemSize64WithUint(off *uint256.Int, length64 uint64) (uint64, bool) { + // if length is zero, memsize is always zero, regardless of offset + if length64 == 0 { + return 0, false + } + // Check that offset doesn't overflow + offset64, overflow := off.Uint64WithOverflow() + if overflow { + return 0, true + } + val := offset64 + length64 + // if value < either of it's parts, then it overflowed + return val, val < offset64 +} + +// getData returns a slice from the data based on the start and size and pads +// up to size with zero's. This function is overflow safe. +func getData(data []byte, start uint64, size uint64) []byte { + length := uint64(len(data)) + if start > length { + start = length + } + end := start + size + if end > length { + end = length + } + return common.RightPadBytes(data[start:end], int(size)) +} + +// toWordSize returns the ceiled word size required for memory expansion. +func toWordSize(size uint64) uint64 { + if size > math.MaxUint64-31 { + return math.MaxUint64/32 + 1 + } + + return (size + 31) / 32 +} + +func allZero(b []byte) bool { + for _, byte := range b { + if byte != 0 { + return false + } + } + return true +} diff --git a/state/runtime/fakevm/contract.go b/state/runtime/fakevm/contract.go new file mode 100644 index 0000000000..c4f4d90a7d --- /dev/null +++ b/state/runtime/fakevm/contract.go @@ -0,0 +1,194 @@ +// Copyright 2015 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 fakevm + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/holiman/uint256" +) + +// ContractRef is a reference to the contract's backing object +type ContractRef interface { + Address() common.Address +} + +// AccountRef implements ContractRef. +// +// Account references are used during EVM initialisation and +// it's primary use is to fetch addresses. Removing this object +// proves difficult because of the cached jump destinations which +// are fetched from the parent contract (i.e. the caller), which +// is a ContractRef. +type AccountRef common.Address + +// Address casts AccountRef to a Address +func (ar AccountRef) Address() common.Address { return (common.Address)(ar) } + +// Contract represents an ethereum contract in the state database. It contains +// the contract code, calling arguments. Contract implements ContractRef +type Contract struct { + // CallerAddress is the result of the caller which initialised this + // contract. However when the "call method" is delegated this value + // needs to be initialised to that of the caller's caller. + CallerAddress common.Address + caller ContractRef + self ContractRef + + jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. + analysis bitvec // Locally cached result of JUMPDEST analysis + + Code []byte + CodeHash common.Hash + CodeAddr *common.Address + Input []byte + + Gas uint64 + value *big.Int +} + +// NewContract returns a new contract environment for the execution of EVM. +func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract { + c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object} + + if parent, ok := caller.(*Contract); ok { + // Reuse JUMPDEST analysis from parent context if available. + c.jumpdests = parent.jumpdests + } else { + c.jumpdests = make(map[common.Hash]bitvec) + } + + // Gas should be a pointer so it can safely be reduced through the run + // This pointer will be off the state transition + c.Gas = gas + // ensures a value is set + c.value = value + + return c +} + +func (c *Contract) validJumpdest(dest *uint256.Int) bool { + udest, overflow := dest.Uint64WithOverflow() + // PC cannot go beyond len(code) and certainly can't be bigger than 63bits. + // Don't bother checking for JUMPDEST in that case. + if overflow || udest >= uint64(len(c.Code)) { + return false + } + // Only JUMPDESTs allowed for destinations + if OpCode(c.Code[udest]) != JUMPDEST { + return false + } + return c.isCode(udest) +} + +// isCode returns true if the provided PC location is an actual opcode, as +// opposed to a data-segment following a PUSHN operation. +func (c *Contract) isCode(udest uint64) bool { + // Do we already have an analysis laying around? + if c.analysis != nil { + return c.analysis.codeSegment(udest) + } + // Do we have a contract hash already? + // If we do have a hash, that means it's a 'regular' contract. For regular + // contracts ( not temporary initcode), we store the analysis in a map + if c.CodeHash != (common.Hash{}) { + // Does parent context have the analysis? + analysis, exist := c.jumpdests[c.CodeHash] + if !exist { + // Do the analysis and save in parent context + // We do not need to store it in c.analysis + analysis = codeBitmap(c.Code) + c.jumpdests[c.CodeHash] = analysis + } + // Also stash it in current contract for faster access + c.analysis = analysis + return analysis.codeSegment(udest) + } + // We don't have the code hash, most likely a piece of initcode not already + // in state trie. In that case, we do an analysis, and save it locally, so + // we don't have to recalculate it for every JUMP instruction in the execution + // However, we don't save it within the parent context + if c.analysis == nil { + c.analysis = codeBitmap(c.Code) + } + return c.analysis.codeSegment(udest) +} + +// AsDelegate sets the contract to be a delegate call and returns the current +// contract (for chaining calls) +func (c *Contract) AsDelegate() *Contract { + // NOTE: caller must, at all times be a contract. It should never happen + // that caller is something other than a Contract. + parent := c.caller.(*Contract) + c.CallerAddress = parent.CallerAddress + c.value = parent.value + + return c +} + +// GetOp returns the n'th element in the contract's byte array +func (c *Contract) GetOp(n uint64) OpCode { + if n < uint64(len(c.Code)) { + return OpCode(c.Code[n]) + } + + return STOP +} + +// Caller returns the caller of the contract. +// +// Caller will recursively call caller when the contract is a delegate +// call, including that of caller's caller. +func (c *Contract) Caller() common.Address { + return c.CallerAddress +} + +// UseGas attempts the use gas and subtracts it and returns true on success +func (c *Contract) UseGas(gas uint64) (ok bool) { + if c.Gas < gas { + return false + } + c.Gas -= gas + return true +} + +// Address returns the contracts address +func (c *Contract) Address() common.Address { + return c.self.Address() +} + +// Value returns the contract's value (sent to it from it's caller) +func (c *Contract) Value() *big.Int { + return c.value +} + +// SetCallCode sets the code of the contract and address of the backing data +// object +func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) { + c.Code = code + c.CodeHash = hash + c.CodeAddr = addr +} + +// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash. +// In case hash is not provided, the jumpdest analysis will not be saved to the parent context +func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) { + c.Code = codeAndHash.code + c.CodeHash = codeAndHash.hash + c.CodeAddr = addr +} diff --git a/state/runtime/fakevm/contracts.go b/state/runtime/fakevm/contracts.go new file mode 100644 index 0000000000..c3ece760dc --- /dev/null +++ b/state/runtime/fakevm/contracts.go @@ -0,0 +1,1050 @@ +// Copyright 2014 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 fakevm + +import ( + "crypto/sha256" + "encoding/binary" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/blake2b" + "github.com/ethereum/go-ethereum/crypto/bls12381" + "github.com/ethereum/go-ethereum/crypto/bn256" + "github.com/ethereum/go-ethereum/params" + "golang.org/x/crypto/ripemd160" +) + +// PrecompiledContract is the basic interface for native Go contracts. The implementation +// requires a deterministic gas count based on the input size of the Run method of the +// contract. +type PrecompiledContract interface { + RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + Run(input []byte) ([]byte, error) // Run runs the precompiled contract +} + +// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum +// contracts used in the Frontier and Homestead releases. +var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, +} + +// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum +// contracts used in the Byzantium release. +var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + common.BytesToAddress([]byte{6}): &bn256AddByzantium{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{}, + common.BytesToAddress([]byte{8}): &bn256PairingByzantium{}, +} + +// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum +// contracts used in the Istanbul release. +var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, +} + +// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum +// contracts used in the Berlin release. +var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, +} + +// PrecompiledContractsBLS contains the set of pre-compiled Ethereum +// contracts specified in EIP-2537. These are exported for testing purposes. +var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{10}): &bls12381G1Add{}, + common.BytesToAddress([]byte{11}): &bls12381G1Mul{}, + common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{}, + common.BytesToAddress([]byte{13}): &bls12381G2Add{}, + common.BytesToAddress([]byte{14}): &bls12381G2Mul{}, + common.BytesToAddress([]byte{15}): &bls12381G2MultiExp{}, + common.BytesToAddress([]byte{16}): &bls12381Pairing{}, + common.BytesToAddress([]byte{17}): &bls12381MapG1{}, + common.BytesToAddress([]byte{18}): &bls12381MapG2{}, +} + +var ( + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address +) + +func init() { + for k := range PrecompiledContractsHomestead { + PrecompiledAddressesHomestead = append(PrecompiledAddressesHomestead, k) + } + for k := range PrecompiledContractsByzantium { + PrecompiledAddressesByzantium = append(PrecompiledAddressesByzantium, k) + } + for k := range PrecompiledContractsIstanbul { + PrecompiledAddressesIstanbul = append(PrecompiledAddressesIstanbul, k) + } + for k := range PrecompiledContractsBerlin { + PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k) + } +} + +// ActivePrecompiles returns the precompiles enabled with the current configuration. +func ActivePrecompiles(rules params.Rules) []common.Address { + switch { + case rules.IsBerlin: + return PrecompiledAddressesBerlin + case rules.IsIstanbul: + return PrecompiledAddressesIstanbul + case rules.IsByzantium: + return PrecompiledAddressesByzantium + default: + return PrecompiledAddressesHomestead + } +} + +// RunPrecompiledContract runs and evaluates the output of a precompiled contract. +// It returns +// - the returned bytes, +// - the _remaining_ gas, +// - any error that occurred +func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) { + gasCost := p.RequiredGas(input) + if suppliedGas < gasCost { + return nil, 0, ErrOutOfGas + } + suppliedGas -= gasCost + output, err := p.Run(input) + return output, suppliedGas, err +} + +// ECRECOVER implemented as a native contract. +type ecrecover struct{} + +func (c *ecrecover) RequiredGas(input []byte) uint64 { + return params.EcrecoverGas +} + +func (c *ecrecover) Run(input []byte) ([]byte, error) { + const ecRecoverInputLength = 128 + + input = common.RightPadBytes(input, ecRecoverInputLength) + // "input" is (hash, v, r, s), each 32 bytes + // but for ecrecover we want (r, s, v) + + r := new(big.Int).SetBytes(input[64:96]) + s := new(big.Int).SetBytes(input[96:128]) + v := input[63] - 27 + + // tighter sig s values input homestead only apply to tx sigs + if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) { + return nil, nil + } + // We must make sure not to modify the 'input', so placing the 'v' along with + // the signature needs to be done on a new allocation + sig := make([]byte, 65) + copy(sig, input[64:128]) + sig[64] = v + // v needs to be at the end for libsecp256k1 + pubKey, err := crypto.Ecrecover(input[:32], sig) + // make sure the public key is a valid one + if err != nil { + return nil, nil + } + + // the first byte of pubkey is bitcoin heritage + return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil +} + +// SHA256 implemented as a native contract. +type sha256hash struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +// +// This method does not require any overflow checking as the input size gas costs +// required for anything significant is so high it's impossible to pay for. +func (c *sha256hash) RequiredGas(input []byte) uint64 { + return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas +} +func (c *sha256hash) Run(input []byte) ([]byte, error) { + h := sha256.Sum256(input) + return h[:], nil +} + +// RIPEMD160 implemented as a native contract. +type ripemd160hash struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +// +// This method does not require any overflow checking as the input size gas costs +// required for anything significant is so high it's impossible to pay for. +func (c *ripemd160hash) RequiredGas(input []byte) uint64 { + return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas +} +func (c *ripemd160hash) Run(input []byte) ([]byte, error) { + ripemd := ripemd160.New() + ripemd.Write(input) + return common.LeftPadBytes(ripemd.Sum(nil), 32), nil +} + +// data copy implemented as a native contract. +type dataCopy struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +// +// This method does not require any overflow checking as the input size gas costs +// required for anything significant is so high it's impossible to pay for. +func (c *dataCopy) RequiredGas(input []byte) uint64 { + return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas +} +func (c *dataCopy) Run(in []byte) ([]byte, error) { + return common.CopyBytes(in), nil +} + +// bigModExp implements a native big integer exponential modular operation. +type bigModExp struct { + eip2565 bool +} + +var ( + big0 = big.NewInt(0) + big1 = big.NewInt(1) + big3 = big.NewInt(3) + big4 = big.NewInt(4) + big7 = big.NewInt(7) + big8 = big.NewInt(8) + big16 = big.NewInt(16) + big20 = big.NewInt(20) + big32 = big.NewInt(32) + big64 = big.NewInt(64) + big96 = big.NewInt(96) + big480 = big.NewInt(480) + big1024 = big.NewInt(1024) + big3072 = big.NewInt(3072) + big199680 = big.NewInt(199680) +) + +// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198 +// +// def mult_complexity(x): +// if x <= 64: return x ** 2 +// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 +// else: return x ** 2 // 16 + 480 * x - 199680 +// +// where is x is max(length_of_MODULUS, length_of_BASE) +func modexpMultComplexity(x *big.Int) *big.Int { + switch { + case x.Cmp(big64) <= 0: + x.Mul(x, x) // x ** 2 + case x.Cmp(big1024) <= 0: + // (x ** 2 // 4 ) + ( 96 * x - 3072) + x = new(big.Int).Add( + new(big.Int).Div(new(big.Int).Mul(x, x), big4), + new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072), + ) + default: + // (x ** 2 // 16) + (480 * x - 199680) + x = new(big.Int).Add( + new(big.Int).Div(new(big.Int).Mul(x, x), big16), + new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680), + ) + } + return x +} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bigModExp) RequiredGas(input []byte) uint64 { + var ( + baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) + expLen = new(big.Int).SetBytes(getData(input, 32, 32)) + modLen = new(big.Int).SetBytes(getData(input, 64, 32)) + ) + if len(input) > 96 { + input = input[96:] + } else { + input = input[:0] + } + // Retrieve the head 32 bytes of exp for the adjusted exponent length + var expHead *big.Int + if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 { + expHead = new(big.Int) + } else { + if expLen.Cmp(big32) > 0 { + expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32)) + } else { + expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64())) + } + } + // Calculate the adjusted exponent length + var msb int + if bitlen := expHead.BitLen(); bitlen > 0 { + msb = bitlen - 1 + } + adjExpLen := new(big.Int) + if expLen.Cmp(big32) > 0 { + adjExpLen.Sub(expLen, big32) + adjExpLen.Mul(big8, adjExpLen) + } + adjExpLen.Add(adjExpLen, big.NewInt(int64(msb))) + // Calculate the gas cost of the operation + gas := new(big.Int).Set(math.BigMax(modLen, baseLen)) + if c.eip2565 { + // EIP-2565 has three changes + // 1. Different multComplexity (inlined here) + // in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565): + // + // def mult_complexity(x): + // ceiling(x/8)^2 + // + //where is x is max(length_of_MODULUS, length_of_BASE) + gas = gas.Add(gas, big7) + gas = gas.Div(gas, big8) + gas.Mul(gas, gas) + + gas.Mul(gas, math.BigMax(adjExpLen, big1)) + // 2. Different divisor (`GQUADDIVISOR`) (3) + gas.Div(gas, big3) + if gas.BitLen() > 64 { + return math.MaxUint64 + } + // 3. Minimum price of 200 gas + if gas.Uint64() < 200 { + return 200 + } + return gas.Uint64() + } + gas = modexpMultComplexity(gas) + gas.Mul(gas, math.BigMax(adjExpLen, big1)) + gas.Div(gas, big20) + + if gas.BitLen() > 64 { + return math.MaxUint64 + } + return gas.Uint64() +} + +func (c *bigModExp) Run(input []byte) ([]byte, error) { + var ( + baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() + expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() + modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() + ) + if len(input) > 96 { + input = input[96:] + } else { + input = input[:0] + } + // Handle a special case when both the base and mod length is zero + if baseLen == 0 && modLen == 0 { + return []byte{}, nil + } + // Retrieve the operands and execute the exponentiation + var ( + base = new(big.Int).SetBytes(getData(input, 0, baseLen)) + exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) + mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) + v []byte + ) + switch { + case mod.BitLen() == 0: + // Modulo 0 is undefined, return zero + return common.LeftPadBytes([]byte{}, int(modLen)), nil + case base.BitLen() == 1: // a bit length of 1 means it's 1 (or -1). + //If base == 1, then we can just return base % mod (if mod >= 1, which it is) + v = base.Mod(base, mod).Bytes() + default: + v = base.Exp(base, exp, mod).Bytes() + } + return common.LeftPadBytes(v, int(modLen)), nil +} + +// newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, +// returning it, or an error if the point is invalid. +func newCurvePoint(blob []byte) (*bn256.G1, error) { + p := new(bn256.G1) + if _, err := p.Unmarshal(blob); err != nil { + return nil, err + } + return p, nil +} + +// newTwistPoint unmarshals a binary blob into a bn256 elliptic curve point, +// returning it, or an error if the point is invalid. +func newTwistPoint(blob []byte) (*bn256.G2, error) { + p := new(bn256.G2) + if _, err := p.Unmarshal(blob); err != nil { + return nil, err + } + return p, nil +} + +// runBn256Add implements the Bn256Add precompile, referenced by both +// Byzantium and Istanbul operations. +func runBn256Add(input []byte) ([]byte, error) { + x, err := newCurvePoint(getData(input, 0, 64)) + if err != nil { + return nil, err + } + y, err := newCurvePoint(getData(input, 64, 64)) + if err != nil { + return nil, err + } + res := new(bn256.G1) + res.Add(x, y) + return res.Marshal(), nil +} + +// bn256Add implements a native elliptic curve point addition conforming to +// Istanbul consensus rules. +type bn256AddIstanbul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasIstanbul +} + +func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) { + return runBn256Add(input) +} + +// bn256AddByzantium implements a native elliptic curve point addition +// conforming to Byzantium consensus rules. +type bn256AddByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256AddGasByzantium +} + +func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) { + return runBn256Add(input) +} + +// runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by +// both Byzantium and Istanbul operations. +func runBn256ScalarMul(input []byte) ([]byte, error) { + p, err := newCurvePoint(getData(input, 0, 64)) + if err != nil { + return nil, err + } + res := new(bn256.G1) + res.ScalarMult(p, new(big.Int).SetBytes(getData(input, 64, 32))) + return res.Marshal(), nil +} + +// bn256ScalarMulIstanbul implements a native elliptic curve scalar +// multiplication conforming to Istanbul consensus rules. +type bn256ScalarMulIstanbul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256ScalarMulGasIstanbul +} + +func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) { + return runBn256ScalarMul(input) +} + +// bn256ScalarMulByzantium implements a native elliptic curve scalar +// multiplication conforming to Byzantium consensus rules. +type bn256ScalarMulByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256ScalarMulGasByzantium +} + +func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) { + return runBn256ScalarMul(input) +} + +var ( + // true32Byte is returned if the bn256 pairing check succeeds. + true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + + // false32Byte is returned if the bn256 pairing check fails. + false32Byte = make([]byte, 32) + + // errBadPairingInput is returned if the bn256 pairing input is invalid. + errBadPairingInput = errors.New("bad elliptic curve pairing size") +) + +// runBn256Pairing implements the Bn256Pairing precompile, referenced by both +// Byzantium and Istanbul operations. +func runBn256Pairing(input []byte) ([]byte, error) { + // Handle some corner cases cheaply + if len(input)%192 > 0 { + return nil, errBadPairingInput + } + // Convert the input into a set of coordinates + var ( + cs []*bn256.G1 + ts []*bn256.G2 + ) + for i := 0; i < len(input); i += 192 { + c, err := newCurvePoint(input[i : i+64]) + if err != nil { + return nil, err + } + t, err := newTwistPoint(input[i+64 : i+192]) + if err != nil { + return nil, err + } + cs = append(cs, c) + ts = append(ts, t) + } + // Execute the pairing checks and return the results + if bn256.PairingCheck(cs, ts) { + return true32Byte, nil + } + return false32Byte, nil +} + +// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve +// conforming to Istanbul consensus rules. +type bn256PairingIstanbul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { + return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul +} + +func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) { + return runBn256Pairing(input) +} + +// bn256PairingByzantium implements a pairing pre-compile for the bn256 curve +// conforming to Byzantium consensus rules. +type bn256PairingByzantium struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { + return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium +} + +func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { + return runBn256Pairing(input) +} + +type blake2F struct{} + +func (c *blake2F) RequiredGas(input []byte) uint64 { + // If the input is malformed, we can't calculate the gas, return 0 and let the + // actual call choke and fault. + if len(input) != blake2FInputLength { + return 0 + } + return uint64(binary.BigEndian.Uint32(input[0:4])) +} + +const ( + blake2FInputLength = 213 + blake2FFinalBlockBytes = byte(1) + blake2FNonFinalBlockBytes = byte(0) +) + +var ( + errBlake2FInvalidInputLength = errors.New("invalid input length") + errBlake2FInvalidFinalFlag = errors.New("invalid final flag") +) + +func (c *blake2F) Run(input []byte) ([]byte, error) { + // Make sure the input is valid (correct length and final flag) + if len(input) != blake2FInputLength { + return nil, errBlake2FInvalidInputLength + } + if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes { + return nil, errBlake2FInvalidFinalFlag + } + // Parse the input into the Blake2b call parameters + var ( + rounds = binary.BigEndian.Uint32(input[0:4]) + final = input[212] == blake2FFinalBlockBytes + + h [8]uint64 + m [16]uint64 + t [2]uint64 + ) + for i := 0; i < 8; i++ { + offset := 4 + i*8 + h[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + for i := 0; i < 16; i++ { + offset := 68 + i*8 + m[i] = binary.LittleEndian.Uint64(input[offset : offset+8]) + } + t[0] = binary.LittleEndian.Uint64(input[196:204]) + t[1] = binary.LittleEndian.Uint64(input[204:212]) + + // Execute the compression function, extract and return the result + blake2b.F(&h, m, t, final, rounds) + + output := make([]byte, 64) + for i := 0; i < 8; i++ { + offset := i * 8 + binary.LittleEndian.PutUint64(output[offset:offset+8], h[i]) + } + return output, nil +} + +var ( + errBLS12381InvalidInputLength = errors.New("invalid input length") + errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") + errBLS12381G1PointSubgroup = errors.New("g1 point is not on correct subgroup") + errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup") +) + +// bls12381G1Add implements EIP-2537 G1Add precompile. +type bls12381G1Add struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { + return params.Bls12381G1AddGas +} + +func (c *bls12381G1Add) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G1Add precompile. + // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). + // > Output is an encoding of addition operation result - single G1 point (`128` bytes). + if len(input) != 256 { + return nil, errBLS12381InvalidInputLength + } + var err error + var p0, p1 *bls12381.PointG1 + + // Initialize G1 + g := bls12381.NewG1() + + // Decode G1 point p_0 + if p0, err = g.DecodePoint(input[:128]); err != nil { + return nil, err + } + // Decode G1 point p_1 + if p1, err = g.DecodePoint(input[128:]); err != nil { + return nil, err + } + + // Compute r = p_0 + p_1 + r := g.New() + g.Add(r, p0, p1) + + // Encode the G1 point result into 128 bytes + return g.EncodePoint(r), nil +} + +// bls12381G1Mul implements EIP-2537 G1Mul precompile. +type bls12381G1Mul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { + return params.Bls12381G1MulGas +} + +func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G1Mul precompile. + // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). + // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). + if len(input) != 160 { + return nil, errBLS12381InvalidInputLength + } + var err error + var p0 *bls12381.PointG1 + + // Initialize G1 + g := bls12381.NewG1() + + // Decode G1 point + if p0, err = g.DecodePoint(input[:128]); err != nil { + return nil, err + } + // Decode scalar value + e := new(big.Int).SetBytes(input[128:]) + + // Compute r = e * p_0 + r := g.New() + g.MulScalar(r, p0, e) + + // Encode the G1 point into 128 bytes + return g.EncodePoint(r), nil +} + +// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. +type bls12381G1MultiExp struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { + // Calculate G1 point, scalar value pair length + k := len(input) / 160 + if k == 0 { + // Return 0 gas for small input length + return 0 + } + // Lookup discount value for G1 point, scalar value pair length + var discount uint64 + if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen { + discount = params.Bls12381MultiExpDiscountTable[k-1] + } else { + discount = params.Bls12381MultiExpDiscountTable[dLen-1] + } + // Calculate gas and return the result + return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 +} + +func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G1MultiExp precompile. + // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). + // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). + k := len(input) / 160 + if len(input) == 0 || len(input)%160 != 0 { + return nil, errBLS12381InvalidInputLength + } + var err error + points := make([]*bls12381.PointG1, k) + scalars := make([]*big.Int, k) + + // Initialize G1 + g := bls12381.NewG1() + + // Decode point scalar pairs + for i := 0; i < k; i++ { + off := 160 * i + t0, t1, t2 := off, off+128, off+160 + // Decode G1 point + if points[i], err = g.DecodePoint(input[t0:t1]); err != nil { + return nil, err + } + // Decode scalar value + scalars[i] = new(big.Int).SetBytes(input[t1:t2]) + } + + // Compute r = e_0 * p_0 + e_1 * p_1 + ... + e_(k-1) * p_(k-1) + r := g.New() + g.MultiExp(r, points, scalars) + + // Encode the G1 point to 128 bytes + return g.EncodePoint(r), nil +} + +// bls12381G2Add implements EIP-2537 G2Add precompile. +type bls12381G2Add struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { + return params.Bls12381G2AddGas +} + +func (c *bls12381G2Add) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G2Add precompile. + // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). + // > Output is an encoding of addition operation result - single G2 point (`256` bytes). + if len(input) != 512 { + return nil, errBLS12381InvalidInputLength + } + var err error + var p0, p1 *bls12381.PointG2 + + // Initialize G2 + g := bls12381.NewG2() + r := g.New() + + // Decode G2 point p_0 + if p0, err = g.DecodePoint(input[:256]); err != nil { + return nil, err + } + // Decode G2 point p_1 + if p1, err = g.DecodePoint(input[256:]); err != nil { + return nil, err + } + + // Compute r = p_0 + p_1 + g.Add(r, p0, p1) + + // Encode the G2 point into 256 bytes + return g.EncodePoint(r), nil +} + +// bls12381G2Mul implements EIP-2537 G2Mul precompile. +type bls12381G2Mul struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { + return params.Bls12381G2MulGas +} + +func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G2MUL precompile logic. + // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). + // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). + if len(input) != 288 { + return nil, errBLS12381InvalidInputLength + } + var err error + var p0 *bls12381.PointG2 + + // Initialize G2 + g := bls12381.NewG2() + + // Decode G2 point + if p0, err = g.DecodePoint(input[:256]); err != nil { + return nil, err + } + // Decode scalar value + e := new(big.Int).SetBytes(input[256:]) + + // Compute r = e * p_0 + r := g.New() + g.MulScalar(r, p0, e) + + // Encode the G2 point into 256 bytes + return g.EncodePoint(r), nil +} + +// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. +type bls12381G2MultiExp struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { + // Calculate G2 point, scalar value pair length + k := len(input) / 288 + if k == 0 { + // Return 0 gas for small input length + return 0 + } + // Lookup discount value for G2 point, scalar value pair length + var discount uint64 + if dLen := len(params.Bls12381MultiExpDiscountTable); k < dLen { + discount = params.Bls12381MultiExpDiscountTable[k-1] + } else { + discount = params.Bls12381MultiExpDiscountTable[dLen-1] + } + // Calculate gas and return the result + return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 +} + +func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 G2MultiExp precompile logic + // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). + // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). + k := len(input) / 288 + if len(input) == 0 || len(input)%288 != 0 { + return nil, errBLS12381InvalidInputLength + } + var err error + points := make([]*bls12381.PointG2, k) + scalars := make([]*big.Int, k) + + // Initialize G2 + g := bls12381.NewG2() + + // Decode point scalar pairs + for i := 0; i < k; i++ { + off := 288 * i + t0, t1, t2 := off, off+256, off+288 + // Decode G1 point + if points[i], err = g.DecodePoint(input[t0:t1]); err != nil { + return nil, err + } + // Decode scalar value + scalars[i] = new(big.Int).SetBytes(input[t1:t2]) + } + + // Compute r = e_0 * p_0 + e_1 * p_1 + ... + e_(k-1) * p_(k-1) + r := g.New() + g.MultiExp(r, points, scalars) + + // Encode the G2 point to 256 bytes. + return g.EncodePoint(r), nil +} + +// bls12381Pairing implements EIP-2537 Pairing precompile. +type bls12381Pairing struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { + return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas +} + +func (c *bls12381Pairing) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 Pairing precompile logic. + // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: + // > - `128` bytes of G1 point encoding + // > - `256` bytes of G2 point encoding + // > Output is a `32` bytes where last single byte is `0x01` if pairing result is equal to multiplicative identity in a pairing target field and `0x00` otherwise + // > (which is equivalent of Big Endian encoding of Solidity values `uint256(1)` and `uin256(0)` respectively). + k := len(input) / 384 + if len(input) == 0 || len(input)%384 != 0 { + return nil, errBLS12381InvalidInputLength + } + + // Initialize BLS12-381 pairing engine + e := bls12381.NewPairingEngine() + g1, g2 := e.G1, e.G2 + + // Decode pairs + for i := 0; i < k; i++ { + off := 384 * i + t0, t1, t2 := off, off+128, off+384 + + // Decode G1 point + p1, err := g1.DecodePoint(input[t0:t1]) + if err != nil { + return nil, err + } + // Decode G2 point + p2, err := g2.DecodePoint(input[t1:t2]) + if err != nil { + return nil, err + } + + // 'point is on curve' check already done, + // Here we need to apply subgroup checks. + if !g1.InCorrectSubgroup(p1) { + return nil, errBLS12381G1PointSubgroup + } + if !g2.InCorrectSubgroup(p2) { + return nil, errBLS12381G2PointSubgroup + } + + // Update pairing engine with G1 and G2 points + e.AddPair(p1, p2) + } + // Prepare 32 byte output + out := make([]byte, 32) + + // Compute pairing and set the result + if e.Check() { + out[31] = 1 + } + return out, nil +} + +// decodeBLS12381FieldElement decodes BLS12-381 elliptic curve field element. +// Removes top 16 bytes of 64 byte input. +func decodeBLS12381FieldElement(in []byte) ([]byte, error) { + if len(in) != 64 { + return nil, errors.New("invalid field element length") + } + // check top bytes + for i := 0; i < 16; i++ { + if in[i] != byte(0x00) { + return nil, errBLS12381InvalidFieldElementTopBytes + } + } + out := make([]byte, 48) + copy(out[:], in[16:]) + return out, nil +} + +// bls12381MapG1 implements EIP-2537 MapG1 precompile. +type bls12381MapG1 struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { + return params.Bls12381MapG1Gas +} + +func (c *bls12381MapG1) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 Map_To_G1 precompile. + // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. + // > Output of this call is `128` bytes and is G1 point following respective encoding rules. + if len(input) != 64 { + return nil, errBLS12381InvalidInputLength + } + + // Decode input field element + fe, err := decodeBLS12381FieldElement(input) + if err != nil { + return nil, err + } + + // Initialize G1 + g := bls12381.NewG1() + + // Compute mapping + r, err := g.MapToCurve(fe) + if err != nil { + return nil, err + } + + // Encode the G1 point to 128 bytes + return g.EncodePoint(r), nil +} + +// bls12381MapG2 implements EIP-2537 MapG2 precompile. +type bls12381MapG2 struct{} + +// RequiredGas returns the gas required to execute the pre-compiled contract. +func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { + return params.Bls12381MapG2Gas +} + +func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { + // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. + // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. + // > Output of this call is `256` bytes and is G2 point following respective encoding rules. + if len(input) != 128 { + return nil, errBLS12381InvalidInputLength + } + + // Decode input field element + fe := make([]byte, 96) + c0, err := decodeBLS12381FieldElement(input[:64]) + if err != nil { + return nil, err + } + copy(fe[48:], c0) + c1, err := decodeBLS12381FieldElement(input[64:]) + if err != nil { + return nil, err + } + copy(fe[:48], c1) + + // Initialize G2 + g := bls12381.NewG2() + + // Compute mapping + r, err := g.MapToCurve(fe) + if err != nil { + return nil, err + } + + // Encode the G2 point to 256 bytes + return g.EncodePoint(r), nil +} diff --git a/state/runtime/fakevm/eips.go b/state/runtime/fakevm/eips.go new file mode 100644 index 0000000000..5c4674e889 --- /dev/null +++ b/state/runtime/fakevm/eips.go @@ -0,0 +1,243 @@ +// 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 fakevm + +import ( + "fmt" + "sort" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" +) + +var activators = map[int]func(*JumpTable){ + 3855: enable3855, + 3860: enable3860, + 3529: enable3529, + 3198: enable3198, + 2929: enable2929, + 2200: enable2200, + 1884: enable1884, + 1344: enable1344, + 1153: enable1153, +} + +// EnableEIP enables the given EIP on the config. +// This operation writes in-place, and callers need to ensure that the globally +// defined jump tables are not polluted. +func EnableEIP(eipNum int, jt *JumpTable) error { + enablerFn, ok := activators[eipNum] + if !ok { + return fmt.Errorf("undefined eip %d", eipNum) + } + enablerFn(jt) + return nil +} + +func ValidEip(eipNum int) bool { + _, ok := activators[eipNum] + return ok +} +func ActivateableEips() []string { + var nums []string + for k := range activators { + nums = append(nums, fmt.Sprintf("%d", k)) + } + sort.Strings(nums) + return nums +} + +// enable1884 applies EIP-1884 to the given jump table: +// - Increase cost of BALANCE to 700 +// - Increase cost of EXTCODEHASH to 700 +// - Increase cost of SLOAD to 800 +// - Define SELFBALANCE, with cost GasFastStep (5) +func enable1884(jt *JumpTable) { + // Gas cost changes + jt[SLOAD].constantGas = params.SloadGasEIP1884 + jt[BALANCE].constantGas = params.BalanceGasEIP1884 + jt[EXTCODEHASH].constantGas = params.ExtcodeHashGasEIP1884 + + // New opcode + jt[SELFBALANCE] = &operation{ + execute: opSelfBalance, + constantGas: GasFastStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } +} + +func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + balance, _ := uint256.FromBig(interpreter.evm.StateDB.GetBalance(scope.Contract.Address())) + scope.Stack.Push(balance) + return nil, nil +} + +// enable1344 applies EIP-1344 (ChainID Opcode) +// - Adds an opcode that returns the current chain’s EIP-155 unique identifier +func enable1344(jt *JumpTable) { + // New opcode + jt[CHAINID] = &operation{ + execute: opChainID, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } +} + +// opChainID implements CHAINID opcode +func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID) + scope.Stack.Push(chainId) + return nil, nil +} + +// enable2200 applies EIP-2200 (Rebalance net-metered SSTORE) +func enable2200(jt *JumpTable) { + jt[SLOAD].constantGas = params.SloadGasEIP2200 + jt[SSTORE].dynamicGas = gasSStoreEIP2200 +} + +// enable2929 enables "EIP-2929: Gas cost increases for state access opcodes" +// https://eips.ethereum.org/EIPS/eip-2929 +func enable2929(jt *JumpTable) { + jt[SSTORE].dynamicGas = gasSStoreEIP2929 + + jt[SLOAD].constantGas = 0 + jt[SLOAD].dynamicGas = gasSLoadEIP2929 + + jt[EXTCODECOPY].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODECOPY].dynamicGas = gasExtCodeCopyEIP2929 + + jt[EXTCODESIZE].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODESIZE].dynamicGas = gasEip2929AccountCheck + + jt[EXTCODEHASH].constantGas = params.WarmStorageReadCostEIP2929 + jt[EXTCODEHASH].dynamicGas = gasEip2929AccountCheck + + jt[BALANCE].constantGas = params.WarmStorageReadCostEIP2929 + jt[BALANCE].dynamicGas = gasEip2929AccountCheck + + jt[CALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[CALL].dynamicGas = gasCallEIP2929 + + jt[CALLCODE].constantGas = params.WarmStorageReadCostEIP2929 + jt[CALLCODE].dynamicGas = gasCallCodeEIP2929 + + jt[STATICCALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[STATICCALL].dynamicGas = gasStaticCallEIP2929 + + jt[DELEGATECALL].constantGas = params.WarmStorageReadCostEIP2929 + jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP2929 + + // This was previously part of the dynamic cost, but we're using it as a constantGas + // factor here + jt[SELFDESTRUCT].constantGas = params.SelfdestructGasEIP150 + jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP2929 +} + +// enable3529 enabled "EIP-3529: Reduction in refunds": +// - Removes refunds for selfdestructs +// - Reduces refunds for SSTORE +// - Reduces max refunds to 20% gas +func enable3529(jt *JumpTable) { + jt[SSTORE].dynamicGas = gasSStoreEIP3529 + jt[SELFDESTRUCT].dynamicGas = gasSelfdestructEIP3529 +} + +// enable3198 applies EIP-3198 (BASEFEE Opcode) +// - Adds an opcode that returns the current block's base fee. +func enable3198(jt *JumpTable) { + // New opcode + jt[BASEFEE] = &operation{ + execute: opBaseFee, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } +} + +// enable1153 applies EIP-1153 "Transient Storage" +// - Adds TLOAD that reads from transient storage +// - Adds TSTORE that writes to transient storage +func enable1153(jt *JumpTable) { + jt[TLOAD] = &operation{ + execute: opTload, + constantGas: params.WarmStorageReadCostEIP2929, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + } + + jt[TSTORE] = &operation{ + execute: opTstore, + constantGas: params.WarmStorageReadCostEIP2929, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + } +} + +// opTload implements TLOAD opcode +func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + loc := scope.Stack.peek() + hash := common.Hash(loc.Bytes32()) + val := interpreter.evm.StateDB.GetTransientState(scope.Contract.Address(), hash) + loc.SetBytes(val.Bytes()) + return nil, nil +} + +// opTstore implements TSTORE opcode +func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + loc := scope.Stack.pop() + val := scope.Stack.pop() + interpreter.evm.StateDB.SetTransientState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32()) + return nil, nil +} + +// opBaseFee implements BASEFEE opcode +func opBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + baseFee, _ := uint256.FromBig(interpreter.evm.Context.BaseFee) + scope.Stack.Push(baseFee) + return nil, nil +} + +// enable3855 applies EIP-3855 (PUSH0 opcode) +func enable3855(jt *JumpTable) { + // New opcode + jt[PUSH0] = &operation{ + execute: opPush0, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } +} + +// opPush0 implements the PUSH0 opcode +func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int)) + return nil, nil +} + +// ebnable3860 enables "EIP-3860: Limit and meter initcode" +// https://eips.ethereum.org/EIPS/eip-3860 +func enable3860(jt *JumpTable) { + jt[CREATE].dynamicGas = gasCreateEip3860 + jt[CREATE2].dynamicGas = gasCreate2Eip3860 +} diff --git a/state/runtime/fakevm/errors.go b/state/runtime/fakevm/errors.go new file mode 100644 index 0000000000..ef52b4e0a1 --- /dev/null +++ b/state/runtime/fakevm/errors.go @@ -0,0 +1,73 @@ +// Copyright 2014 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 fakevm + +import ( + "errors" + "fmt" +) + +// List evm execution errors +var ( + ErrOutOfGas = errors.New("out of gas") + ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") + ErrDepth = errors.New("max call depth exceeded") + ErrInsufficientBalance = errors.New("insufficient balance for transfer") + ErrContractAddressCollision = errors.New("contract address collision") + ErrExecutionReverted = errors.New("execution reverted") + ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded") + ErrMaxCodeSizeExceeded = errors.New("max code size exceeded") + ErrInvalidJump = errors.New("invalid jump destination") + ErrWriteProtection = errors.New("write protection") + ErrReturnDataOutOfBounds = errors.New("return data out of bounds") + ErrGasUintOverflow = errors.New("gas uint64 overflow") + ErrInvalidCode = errors.New("invalid code: must not begin with 0xef") + ErrNonceUintOverflow = errors.New("nonce uint64 overflow") + + // errStopToken is an internal token indicating interpreter loop termination, + // never returned to outside callers. + errStopToken = errors.New("stop token") +) + +// ErrStackUnderflow wraps an evm error when the items on the stack less +// than the minimal requirement. +type ErrStackUnderflow struct { + stackLen int + required int +} + +func (e *ErrStackUnderflow) Error() string { + return fmt.Sprintf("stack underflow (%d <=> %d)", e.stackLen, e.required) +} + +// ErrStackOverflow wraps an evm error when the items on the stack exceeds +// the maximum allowance. +type ErrStackOverflow struct { + stackLen int + limit int +} + +func (e *ErrStackOverflow) Error() string { + return fmt.Sprintf("stack limit reached %d (%d)", e.stackLen, e.limit) +} + +// ErrInvalidOpCode wraps an evm error when an invalid opcode is encountered. +type ErrInvalidOpCode struct { + opcode OpCode +} + +func (e *ErrInvalidOpCode) Error() string { return fmt.Sprintf("invalid opcode: %s", e.opcode) } diff --git a/state/runtime/fakevm/fakedb.go b/state/runtime/fakevm/fakedb.go index f6d521ee33..47d87815e8 100644 --- a/state/runtime/fakevm/fakedb.go +++ b/state/runtime/fakevm/fakedb.go @@ -4,15 +4,74 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" ) // FakeDB is the interface state access for the FakeEVM type FakeDB interface { SetStateRoot(stateRoot []byte) - GetBalance(address common.Address) *big.Int - GetNonce(address common.Address) uint64 - GetCode(address common.Address) []byte - GetState(address common.Address, hash common.Hash) common.Hash - Exist(address common.Address) bool - GetCodeHash(address common.Address) common.Hash + CreateAccount(common.Address) + + SubBalance(common.Address, *big.Int) + AddBalance(common.Address, *big.Int) + GetBalance(common.Address) *big.Int + + GetNonce(common.Address) uint64 + SetNonce(common.Address, uint64) + + GetCodeHash(common.Address) common.Hash + GetCode(common.Address) []byte + SetCode(common.Address, []byte) + GetCodeSize(common.Address) int + + AddRefund(uint64) + SubRefund(uint64) + GetRefund() uint64 + + GetCommittedState(common.Address, common.Hash) common.Hash + GetState(common.Address, common.Hash) common.Hash + SetState(common.Address, common.Hash, common.Hash) + + GetTransientState(addr common.Address, key common.Hash) common.Hash + SetTransientState(addr common.Address, key, value common.Hash) + + Suicide(common.Address) bool + HasSuicided(common.Address) bool + + // Exist reports whether the given account exists in state. + // Notably this should also return true for suicided accounts. + Exist(common.Address) bool + // Empty returns whether the given account is empty. Empty + // is defined according to EIP161 (balance = nonce = code = 0). + Empty(common.Address) bool + + AddressInAccessList(addr common.Address) bool + SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) + // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform + // even if the feature/fork is not active yet + AddAddressToAccessList(addr common.Address) + // AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform + // even if the feature/fork is not active yet + AddSlotToAccessList(addr common.Address, slot common.Hash) + Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) + + RevertToSnapshot(int) + Snapshot() int + + AddLog(*types.Log) + AddPreimage(common.Hash, []byte) +} + +// CallContext provides a basic interface for the EVM calling conventions. The EVM +// depends on this context being implemented for doing subcalls and initialising new EVM contracts. +type CallContext interface { + // Call calls another contract. + Call(env *FakeEVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) + // CallCode takes another contracts code and execute within our own context + CallCode(env *FakeEVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) + // DelegateCall is same as CallCode except sender and value is propagated from parent to child scope + DelegateCall(env *FakeEVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) + // Create creates a new contract + Create(env *FakeEVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) } diff --git a/state/runtime/fakevm/fakevm.go b/state/runtime/fakevm/fakevm.go index b969f91b32..5cc0ab3049 100644 --- a/state/runtime/fakevm/fakevm.go +++ b/state/runtime/fakevm/fakevm.go @@ -1,22 +1,108 @@ +// Copyright 2014 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 fakevm import ( + "math/big" "sync/atomic" - "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" +) + +// emptyCodeHash is used by create to ensure deployment is disallowed to already +// deployed contract addresses (relevant after the account abstraction). +var emptyCodeHash = crypto.Keccak256Hash(nil) + +type ( + // CanTransferFunc is the signature of a transfer guard function + CanTransferFunc func(FakeDB, common.Address, *big.Int) bool + // TransferFunc is the signature of a transfer function + TransferFunc func(FakeDB, common.Address, common.Address, *big.Int) + // GetHashFunc returns the n'th block hash in the blockchain + // and is used by the BLOCKHASH EVM op code. + GetHashFunc func(uint64) common.Hash ) -// MemoryItemSize is the memory item size. -const MemoryItemSize int = 32 +func (evm *FakeEVM) precompile(addr common.Address) (PrecompiledContract, bool) { + var precompiles map[common.Address]PrecompiledContract + switch { + case evm.chainRules.IsBerlin: + precompiles = PrecompiledContractsBerlin + case evm.chainRules.IsIstanbul: + precompiles = PrecompiledContractsIstanbul + case evm.chainRules.IsByzantium: + precompiles = PrecompiledContractsByzantium + default: + precompiles = PrecompiledContractsHomestead + } + p, ok := precompiles[addr] + return p, ok +} + +// BlockContext provides the EVM with auxiliary information. Once provided +// it shouldn't be modified. +type BlockContext struct { + // CanTransfer returns whether the account contains + // sufficient ether to transfer the value + CanTransfer CanTransferFunc + // Transfer transfers ether from one account to the other + Transfer TransferFunc + // GetHash returns the hash corresponding to n + GetHash GetHashFunc + + // Block information + Coinbase common.Address // Provides information for COINBASE + GasLimit uint64 // Provides information for GASLIMIT + BlockNumber *big.Int // Provides information for NUMBER + Time uint64 // Provides information for TIME + Difficulty *big.Int // Provides information for DIFFICULTY + BaseFee *big.Int // Provides information for BASEFEE + Random *common.Hash // Provides information for PREVRANDAO +} + +// TxContext provides the EVM with information about a transaction. +// All fields can change between transactions. +type TxContext struct { + // Message information + Origin common.Address // Provides information for ORIGIN + GasPrice *big.Int // Provides information for GASPRICE +} -// FakeEVM represents the fake EVM. +// FakeEVM is the Ethereum Virtual Machine base object and provides +// the necessary tools to run a contract on the given state with +// the provided context. It should be noted that any error +// generated through any of the calls should be considered a +// revert-state-and-consume-all-gas operation, no checks on +// specific errors should ever be performed. The interpreter makes +// sure that any errors generated are to be considered faulty code. +// +// The FakeEVM should never be reused and is not thread safe. type FakeEVM struct { // Context provides auxiliary blockchain related information - Context vm.BlockContext - vm.TxContext + Context BlockContext + TxContext // StateDB gives access to the underlying state StateDB FakeDB + // Depth is the current call stack + depth int + // chainConfig contains information about the current chain chainConfig *params.ChainConfig // chain rules contains the chain rules for the current epoch @@ -24,28 +110,38 @@ type FakeEVM struct { // virtual machine configuration options used to initialise the // evm. Config Config + // global (to this context) ethereum virtual machine + // used throughout the execution of the tx. + interpreter *EVMInterpreter // abort is used to abort the EVM calling operations // NOTE: must be set atomically abort int32 + // callGasTemp holds the gas available for the current call. This is needed because the + // available gas is calculated in gasCall* according to the 63/64 rule and later + // applied in opCall*. + callGasTemp uint64 } // NewFakeEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -// func NewFakeEVM(blockCtx vm.BlockContext, txCtx vm.TxContext, statedb runtime.FakeDB, chainConfig *params.ChainConfig, config Config) *FakeEVM { -func NewFakeEVM(blockCtx vm.BlockContext, txCtx vm.TxContext, chainConfig *params.ChainConfig, config Config) *FakeEVM { +func NewFakeEVM(blockCtx BlockContext, txCtx TxContext, statedb FakeDB, chainConfig *params.ChainConfig, config Config) *FakeEVM { evm := &FakeEVM{ Context: blockCtx, TxContext: txCtx, + StateDB: statedb, Config: config, chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), } + evm.interpreter = NewEVMInterpreter(evm) return evm } -// SetStateDB is the StateDB setter. -func (evm *FakeEVM) SetStateDB(stateDB FakeDB) { - evm.StateDB = stateDB +// Reset resets the EVM with a new transaction context.Reset +// This is not threadsafe and should only be done very cautiously. +func (evm *FakeEVM) Reset(txCtx TxContext, statedb FakeDB) { + evm.TxContext = txCtx + evm.StateDB = statedb } // Cancel cancels any running EVM operation. This may be called concurrently and @@ -54,13 +150,375 @@ func (evm *FakeEVM) Cancel() { atomic.StoreInt32(&evm.abort, 1) } -// ChainConfig returns the environment's chain configuration -func (evm *FakeEVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } +// Cancelled returns true if Cancel has been called +func (evm *FakeEVM) Cancelled() bool { + return atomic.LoadInt32(&evm.abort) == 1 +} + +// Interpreter returns the current interpreter +func (evm *FakeEVM) Interpreter() *EVMInterpreter { + return evm.interpreter +} + +// SetBlockContext updates the block context of the EVM. +func (evm *FakeEVM) SetBlockContext(blockCtx BlockContext) { + evm.Context = blockCtx + num := blockCtx.BlockNumber + timestamp := blockCtx.Time + evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp) +} + +// Call executes the contract associated with the addr with the given input as +// parameters. It also handles any necessary value transfer required and takes +// the necessary steps to create accounts and reverses the state in case of an +// execution error or failed value transfer. +func (evm *FakeEVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { + // Fail if we're trying to execute above the call depth limit + if evm.depth > int(params.CallCreateDepth) { + return nil, gas, ErrDepth + } + // Fail if we're trying to transfer more than the available balance + if value.Sign() != 0 && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + return nil, gas, ErrInsufficientBalance + } + snapshot := evm.StateDB.Snapshot() + p, isPrecompile := evm.precompile(addr) + + if !evm.StateDB.Exist(addr) { + if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { + // Calling a non existing account, don't do anything, but ping the tracer + if evm.Config.Debug { + if evm.depth == 0 { + evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + evm.Config.Tracer.CaptureEnd(ret, 0, nil) + } else { + evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) + evm.Config.Tracer.CaptureExit(ret, 0, nil) + } + } + return nil, gas, nil + } + evm.StateDB.CreateAccount(addr) + } + evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) + + // Capture the tracer start/end events in debug mode + if evm.Config.Debug { + if evm.depth == 0 { + evm.Config.Tracer.CaptureStart(evm, caller.Address(), addr, false, input, gas, value) + defer func(startGas uint64) { // Lazy evaluation of the parameters + evm.Config.Tracer.CaptureEnd(ret, startGas-gas, err) + }(gas) + } else { + // Handle tracer events for entering and exiting a call frame + evm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value) + defer func(startGas uint64) { + evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) + }(gas) + } + } + + if isPrecompile { + ret, gas, err = RunPrecompiledContract(p, input, gas) + } else { + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. + code := evm.StateDB.GetCode(addr) + if len(code) == 0 { + ret, err = nil, nil // gas is unchanged + } else { + addrCopy := addr + // If the account has no code, we can abort here + // The depth-check is already done, and precompiles handled above + contract := NewContract(caller, AccountRef(addrCopy), value, gas) + contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), code) + ret, err = evm.interpreter.Run(contract, input, false) + gas = contract.Gas + } + } + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in homestead this also counts for code storage gas errors. + if err != nil { + evm.StateDB.RevertToSnapshot(snapshot) + if err != ErrExecutionReverted { + gas = 0 + } + // TODO: consider clearing up unused snapshots: + //} else { + // evm.StateDB.DiscardSnapshot(snapshot) + } + return ret, gas, err +} + +// CallCode executes the contract associated with the addr with the given input +// as parameters. It also handles any necessary value transfer required and takes +// the necessary steps to create accounts and reverses the state in case of an +// execution error or failed value transfer. +// +// CallCode differs from Call in the sense that it executes the given address' +// code with the caller as context. +func (evm *FakeEVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { + // Fail if we're trying to execute above the call depth limit + if evm.depth > int(params.CallCreateDepth) { + return nil, gas, ErrDepth + } + // Fail if we're trying to transfer more than the available balance + // Note although it's noop to transfer X ether to caller itself. But + // if caller doesn't have enough balance, it would be an error to allow + // over-charging itself. So the check here is necessary. + if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + return nil, gas, ErrInsufficientBalance + } + var snapshot = evm.StateDB.Snapshot() + + // Invoke tracer hooks that signal entering/exiting a call frame + if evm.Config.Debug { + evm.Config.Tracer.CaptureEnter(CALLCODE, caller.Address(), addr, input, gas, value) + defer func(startGas uint64) { + evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) + }(gas) + } + + // It is allowed to call precompiles, even via delegatecall + if p, isPrecompile := evm.precompile(addr); isPrecompile { + ret, gas, err = RunPrecompiledContract(p, input, gas) + } else { + addrCopy := addr + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. + contract := NewContract(caller, AccountRef(caller.Address()), value, gas) + contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) + ret, err = evm.interpreter.Run(contract, input, false) + gas = contract.Gas + } + if err != nil { + evm.StateDB.RevertToSnapshot(snapshot) + if err != ErrExecutionReverted { + gas = 0 + } + } + return ret, gas, err +} + +// DelegateCall executes the contract associated with the addr with the given input +// as parameters. It reverses the state in case of an execution error. +// +// DelegateCall differs from CallCode in the sense that it executes the given address' +// code with the caller as context and the caller is set to the caller of the caller. +func (evm *FakeEVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { + // Fail if we're trying to execute above the call depth limit + if evm.depth > int(params.CallCreateDepth) { + return nil, gas, ErrDepth + } + var snapshot = evm.StateDB.Snapshot() + + // Invoke tracer hooks that signal entering/exiting a call frame + if evm.Config.Debug { + // NOTE: caller must, at all times be a contract. It should never happen + // that caller is something other than a Contract. + parent := caller.(*Contract) + // DELEGATECALL inherits value from parent call + evm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value) + defer func(startGas uint64) { + evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) + }(gas) + } + + // It is allowed to call precompiles, even via delegatecall + if p, isPrecompile := evm.precompile(addr); isPrecompile { + ret, gas, err = RunPrecompiledContract(p, input, gas) + } else { + addrCopy := addr + // Initialise a new contract and make initialise the delegate values + contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() + contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) + ret, err = evm.interpreter.Run(contract, input, false) + gas = contract.Gas + } + if err != nil { + evm.StateDB.RevertToSnapshot(snapshot) + if err != ErrExecutionReverted { + gas = 0 + } + } + return ret, gas, err +} + +// StaticCall executes the contract associated with the addr with the given input +// as parameters while disallowing any modifications to the state during the call. +// Opcodes that attempt to perform such modifications will result in exceptions +// instead of performing the modifications. +func (evm *FakeEVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { + // Fail if we're trying to execute above the call depth limit + if evm.depth > int(params.CallCreateDepth) { + return nil, gas, ErrDepth + } + // We take a snapshot here. This is a bit counter-intuitive, and could probably be skipped. + // However, even a staticcall is considered a 'touch'. On mainnet, static calls were introduced + // after all empty accounts were deleted, so this is not required. However, if we omit this, + // then certain tests start failing; stRevertTest/RevertPrecompiledTouchExactOOG.json. + // We could change this, but for now it's left for legacy reasons + var snapshot = evm.StateDB.Snapshot() + + // We do an AddBalance of zero here, just in order to trigger a touch. + // This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, + // but is the correct thing to do and matters on other networks, in tests, and potential + // future scenarios + evm.StateDB.AddBalance(addr, big0) + + // Invoke tracer hooks that signal entering/exiting a call frame + if evm.Config.Debug { + evm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil) + defer func(startGas uint64) { + evm.Config.Tracer.CaptureExit(ret, startGas-gas, err) + }(gas) + } + + if p, isPrecompile := evm.precompile(addr); isPrecompile { + ret, gas, err = RunPrecompiledContract(p, input, gas) + } else { + // At this point, we use a copy of address. If we don't, the go compiler will + // leak the 'contract' to the outer scope, and make allocation for 'contract' + // even if the actual execution ends on RunPrecompiled above. + addrCopy := addr + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. + contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas) + contract.SetCallCode(&addrCopy, evm.StateDB.GetCodeHash(addrCopy), evm.StateDB.GetCode(addrCopy)) + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in Homestead this also counts for code storage gas errors. + ret, err = evm.interpreter.Run(contract, input, true) + gas = contract.Gas + } + if err != nil { + evm.StateDB.RevertToSnapshot(snapshot) + if err != ErrExecutionReverted { + gas = 0 + } + } + return ret, gas, err +} + +type codeAndHash struct { + code []byte + hash common.Hash +} + +func (c *codeAndHash) Hash() common.Hash { + if c.hash == (common.Hash{}) { + c.hash = crypto.Keccak256Hash(c.code) + } + return c.hash +} + +// create creates a new contract using code as deployment code. +func (evm *FakeEVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) { + // Depth check execution. Fail if we're trying to execute above the + // limit. + if evm.depth > int(params.CallCreateDepth) { + return nil, common.Address{}, gas, ErrDepth + } + if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + return nil, common.Address{}, gas, ErrInsufficientBalance + } + nonce := evm.StateDB.GetNonce(caller.Address()) + if nonce+1 < nonce { + return nil, common.Address{}, gas, ErrNonceUintOverflow + } + evm.StateDB.SetNonce(caller.Address(), nonce+1) + // We add this to the access list _before_ taking a snapshot. Even if the creation fails, + // the access-list change should not be rolled back + if evm.chainRules.IsBerlin { + evm.StateDB.AddAddressToAccessList(address) + } + // Ensure there's no existing contract already at the designated address + contractHash := evm.StateDB.GetCodeHash(address) + if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { + return nil, common.Address{}, 0, ErrContractAddressCollision + } + // Create a new account on the state + snapshot := evm.StateDB.Snapshot() + evm.StateDB.CreateAccount(address) + if evm.chainRules.IsEIP158 { + evm.StateDB.SetNonce(address, 1) + } + evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) + + // Initialise a new contract and set the code that is to be used by the EVM. + // The contract is a scoped environment for this execution context only. + contract := NewContract(caller, AccountRef(address), value, gas) + contract.SetCodeOptionalHash(&address, codeAndHash) + + if evm.Config.Debug { + if evm.depth == 0 { + evm.Config.Tracer.CaptureStart(evm, caller.Address(), address, true, codeAndHash.code, gas, value) + } else { + evm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value) + } + } + + ret, err := evm.interpreter.Run(contract, nil, false) + + // Check whether the max code size has been exceeded, assign err if the case. + if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize { + err = ErrMaxCodeSizeExceeded + } + + // Reject code starting with 0xEF if EIP-3541 is enabled. + if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon { + err = ErrInvalidCode + } + + // if the contract creation ran successfully and no errors were returned + // calculate the gas required to store the code. If the code could not + // be stored due to not enough gas set an error and let it be handled + // by the error checking condition below. + if err == nil { + createDataGas := uint64(len(ret)) * params.CreateDataGas + if contract.UseGas(createDataGas) { + evm.StateDB.SetCode(address, ret) + } else { + err = ErrCodeStoreOutOfGas + } + } + + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in homestead this also counts for code storage gas errors. + if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { + evm.StateDB.RevertToSnapshot(snapshot) + if err != ErrExecutionReverted { + contract.UseGas(contract.Gas) + } + } + + if evm.Config.Debug { + if evm.depth == 0 { + evm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err) + } else { + evm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err) + } + } + return ret, address, contract.Gas, err +} -// ScopeContext contains the things that are per-call, such as stack and memory, -// but not transients like pc and gas -type ScopeContext struct { - Memory *Memory - Stack *Stack - Contract *vm.Contract +// Create creates a new contract using code as deployment code. +func (evm *FakeEVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) + return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) } + +// Create2 creates a new contract using code as deployment code. +// +// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] +// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. +func (evm *FakeEVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { + codeAndHash := &codeAndHash{code: code} + contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) + return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) +} + +// ChainConfig returns the environment's chain configuration +func (evm *FakeEVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } diff --git a/state/runtime/fakevm/gas.go b/state/runtime/fakevm/gas.go new file mode 100644 index 0000000000..4ccf3da204 --- /dev/null +++ b/state/runtime/fakevm/gas.go @@ -0,0 +1,53 @@ +// Copyright 2015 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 fakevm + +import ( + "github.com/holiman/uint256" +) + +// Gas costs +const ( + GasQuickStep uint64 = 2 + GasFastestStep uint64 = 3 + GasFastStep uint64 = 5 + GasMidStep uint64 = 8 + GasSlowStep uint64 = 10 + GasExtStep uint64 = 20 +) + +// callGas returns the actual gas cost of the call. +// +// The cost of gas was changed during the homestead price change HF. +// As part of EIP 150 (TangerineWhistle), the returned gas is gas - base * 63 / 64. +func callGas(isEip150 bool, availableGas, base uint64, callCost *uint256.Int) (uint64, error) { + if isEip150 { + availableGas = availableGas - base + gas := availableGas - availableGas/64 + // If the bit length exceeds 64 bit we know that the newly calculated "gas" for EIP150 + // is smaller than the requested amount. Therefore we return the new gas instead + // of returning an error. + if !callCost.IsUint64() || gas < callCost.Uint64() { + return gas, nil + } + } + if !callCost.IsUint64() { + return 0, ErrGasUintOverflow + } + + return callCost.Uint64(), nil +} diff --git a/state/runtime/fakevm/gas_table.go b/state/runtime/fakevm/gas_table.go new file mode 100644 index 0000000000..31e4859dc2 --- /dev/null +++ b/state/runtime/fakevm/gas_table.go @@ -0,0 +1,477 @@ +// Copyright 2017 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 fakevm + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/params" +) + +// memoryGasCost calculates the quadratic gas for memory expansion. It does so +// only for the memory region that is expanded, not the total memory. +func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) { + if newMemSize == 0 { + return 0, nil + } + // The maximum that will fit in a uint64 is max_word_count - 1. Anything above + // that will result in an overflow. Additionally, a newMemSize which results in + // a newMemSizeWords larger than 0xFFFFFFFF will cause the square operation to + // overflow. The constant 0x1FFFFFFFE0 is the highest number that can be used + // without overflowing the gas calculation. + if newMemSize > 0x1FFFFFFFE0 { + return 0, ErrGasUintOverflow + } + newMemSizeWords := toWordSize(newMemSize) + newMemSize = newMemSizeWords * 32 + + if newMemSize > uint64(mem.Len()) { + square := newMemSizeWords * newMemSizeWords + linCoef := newMemSizeWords * params.MemoryGas + quadCoef := square / params.QuadCoeffDiv + newTotalFee := linCoef + quadCoef + + fee := newTotalFee - mem.lastGasCost + mem.lastGasCost = newTotalFee + + return fee, nil + } + return 0, nil +} + +// memoryCopierGas creates the gas functions for the following opcodes, and takes +// the stack position of the operand which determines the size of the data to copy +// as argument: +// CALLDATACOPY (stack position 2) +// CODECOPY (stack position 2) +// EXTCODECOPY (stack position 3) +// RETURNDATACOPY (stack position 2) +func memoryCopierGas(stackpos int) gasFunc { + return func(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // Gas for expanding the memory + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + // And gas for copying data, charged per word at param.CopyGas + words, overflow := stack.Back(stackpos).Uint64WithOverflow() + if overflow { + return 0, ErrGasUintOverflow + } + + if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { + return 0, ErrGasUintOverflow + } + + if gas, overflow = math.SafeAdd(gas, words); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil + } +} + +var ( + gasCallDataCopy = memoryCopierGas(2) + gasCodeCopy = memoryCopierGas(2) + gasExtCodeCopy = memoryCopierGas(3) + gasReturnDataCopy = memoryCopierGas(2) +) + +func gasSStore(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var ( + y, x = stack.Back(1), stack.Back(0) + current = evm.StateDB.GetState(contract.Address(), x.Bytes32()) + ) + // The legacy gas metering only takes into consideration the current state + // Legacy rules should be applied if we are in Petersburg (removal of EIP-1283) + // OR Constantinople is not active + if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople { + // This checks for 3 scenario's and calculates gas accordingly: + // + // 1. From a zero-value address to a non-zero value (NEW VALUE) + // 2. From a non-zero value address to a zero-value address (DELETE) + // 3. From a non-zero to a non-zero (CHANGE) + switch { + case current == (common.Hash{}) && y.Sign() != 0: // 0 => non 0 + return params.SstoreSetGas, nil + case current != (common.Hash{}) && y.Sign() == 0: // non 0 => 0 + evm.StateDB.AddRefund(params.SstoreRefundGas) + return params.SstoreClearGas, nil + default: // non 0 => non 0 (or 0 => 0) + return params.SstoreResetGas, nil + } + } + + // The new gas metering is based on net gas costs (EIP-1283): + // + // (1.) If current value equals new value (this is a no-op), 200 gas is deducted. + // (2.) If current value does not equal new value + // (2.1.) If original value equals current value (this storage slot has not been changed by the current execution context) + // (2.1.1.) If original value is 0, 20000 gas is deducted. + // (2.1.2.) Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter. + // (2.2.) If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + // (2.2.1.) If original value is not 0 + // (2.2.1.1.) If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + // (2.2.1.2.) If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + // (2.2.2.) If original value equals new value (this storage slot is reset) + // (2.2.2.1.) If original value is 0, add 19800 gas to refund counter. + // (2.2.2.2.) Otherwise, add 4800 gas to refund counter. + value := common.Hash(y.Bytes32()) + if current == value { // noop (1) + return params.NetSstoreNoopGas, nil + } + original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) + if original == current { + if original == (common.Hash{}) { // create slot (2.1.1) + return params.NetSstoreInitGas, nil + } + if value == (common.Hash{}) { // delete slot (2.1.2b) + evm.StateDB.AddRefund(params.NetSstoreClearRefund) + } + return params.NetSstoreCleanGas, nil // write existing slot (2.1.2) + } + if original != (common.Hash{}) { + if current == (common.Hash{}) { // recreate slot (2.2.1.1) + evm.StateDB.SubRefund(params.NetSstoreClearRefund) + } else if value == (common.Hash{}) { // delete slot (2.2.1.2) + evm.StateDB.AddRefund(params.NetSstoreClearRefund) + } + } + if original == value { + if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1) + evm.StateDB.AddRefund(params.NetSstoreResetClearRefund) + } else { // reset to original existing slot (2.2.2.2) + evm.StateDB.AddRefund(params.NetSstoreResetRefund) + } + } + return params.NetSstoreDirtyGas, nil +} + +// Here come the EIP2200 rules: +// +// (0.) If *gasleft* is less than or equal to 2300, fail the current call. +// (1.) If current value equals new value (this is a no-op), SLOAD_GAS is deducted. +// (2.) If current value does not equal new value: +// (2.1.) If original value equals current value (this storage slot has not been changed by the current execution context): +// (2.1.1.) If original value is 0, SSTORE_SET_GAS (20K) gas is deducted. +// (2.1.2.) Otherwise, SSTORE_RESET_GAS gas is deducted. If new value is 0, add SSTORE_CLEARS_SCHEDULE to refund counter. +// (2.2.) If original value does not equal current value (this storage slot is dirty), SLOAD_GAS gas is deducted. Apply both of the following clauses: +// (2.2.1.) If original value is not 0: +// (2.2.1.1.) If current value is 0 (also means that new value is not 0), subtract SSTORE_CLEARS_SCHEDULE gas from refund counter. +// (2.2.1.2.) If new value is 0 (also means that current value is not 0), add SSTORE_CLEARS_SCHEDULE gas to refund counter. +// (2.2.2.) If original value equals new value (this storage slot is reset): +// (2.2.2.1.) If original value is 0, add SSTORE_SET_GAS - SLOAD_GAS to refund counter. +// (2.2.2.2.) Otherwise, add SSTORE_RESET_GAS - SLOAD_GAS gas to refund counter. +func gasSStoreEIP2200(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // If we fail the minimum gas availability invariant, fail (0) + if contract.Gas <= params.SstoreSentryGasEIP2200 { + return 0, errors.New("not enough gas for reentrancy sentry") + } + // Gas sentry honoured, do the actual gas calculation based on the stored value + var ( + y, x = stack.Back(1), stack.Back(0) + current = evm.StateDB.GetState(contract.Address(), x.Bytes32()) + ) + value := common.Hash(y.Bytes32()) + + if current == value { // noop (1) + return params.SloadGasEIP2200, nil + } + original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) + if original == current { + if original == (common.Hash{}) { // create slot (2.1.1) + return params.SstoreSetGasEIP2200, nil + } + if value == (common.Hash{}) { // delete slot (2.1.2b) + evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200) + } + return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2) + } + if original != (common.Hash{}) { + if current == (common.Hash{}) { // recreate slot (2.2.1.1) + evm.StateDB.SubRefund(params.SstoreClearsScheduleRefundEIP2200) + } else if value == (common.Hash{}) { // delete slot (2.2.1.2) + evm.StateDB.AddRefund(params.SstoreClearsScheduleRefundEIP2200) + } + } + if original == value { + if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1) + evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200) + } else { // reset to original existing slot (2.2.2.2) + evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200) + } + } + return params.SloadGasEIP2200, nil // dirty update (2.2) +} + +func makeGasLog(n uint64) gasFunc { + return func(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + requestedSize, overflow := stack.Back(1).Uint64WithOverflow() + if overflow { + return 0, ErrGasUintOverflow + } + + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + + if gas, overflow = math.SafeAdd(gas, params.LogGas); overflow { + return 0, ErrGasUintOverflow + } + if gas, overflow = math.SafeAdd(gas, n*params.LogTopicGas); overflow { + return 0, ErrGasUintOverflow + } + + var memorySizeGas uint64 + if memorySizeGas, overflow = math.SafeMul(requestedSize, params.LogDataGas); overflow { + return 0, ErrGasUintOverflow + } + if gas, overflow = math.SafeAdd(gas, memorySizeGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil + } +} + +func gasKeccak256(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + wordGas, overflow := stack.Back(1).Uint64WithOverflow() + if overflow { + return 0, ErrGasUintOverflow + } + if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow { + return 0, ErrGasUintOverflow + } + if gas, overflow = math.SafeAdd(gas, wordGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +// pureMemoryGascost is used by several operations, which aside from their +// static cost have a dynamic cost which is solely based on the memory +// expansion +func pureMemoryGascost(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + return memoryGasCost(mem, memorySize) +} + +var ( + gasReturn = pureMemoryGascost + gasRevert = pureMemoryGascost + gasMLoad = pureMemoryGascost + gasMStore8 = pureMemoryGascost + gasMStore = pureMemoryGascost + gasCreate = pureMemoryGascost +) + +func gasCreate2(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + wordGas, overflow := stack.Back(2).Uint64WithOverflow() + if overflow { + return 0, ErrGasUintOverflow + } + if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow { + return 0, ErrGasUintOverflow + } + if gas, overflow = math.SafeAdd(gas, wordGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasCreateEip3860(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + size, overflow := stack.Back(2).Uint64WithOverflow() + if overflow || size > params.MaxInitCodeSize { + return 0, ErrGasUintOverflow + } + // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow + moreGas := params.InitCodeWordGas * ((size + 31) / 32) + if gas, overflow = math.SafeAdd(gas, moreGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} +func gasCreate2Eip3860(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + size, overflow := stack.Back(2).Uint64WithOverflow() + if overflow || size > params.MaxInitCodeSize { + return 0, ErrGasUintOverflow + } + // Since size <= params.MaxInitCodeSize, these multiplication cannot overflow + moreGas := (params.InitCodeWordGas + params.Keccak256WordGas) * ((size + 31) / 32) + if gas, overflow = math.SafeAdd(gas, moreGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasExpFrontier(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) + + var ( + gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas + overflow bool + ) + if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasExpEIP158(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8) + + var ( + gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas + overflow bool + ) + if gas, overflow = math.SafeAdd(gas, params.ExpGas); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasCall(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var ( + gas uint64 + transfersValue = !stack.Back(2).IsZero() + address = common.Address(stack.Back(1).Bytes20()) + ) + if evm.chainRules.IsEIP158 { + if transfersValue && evm.StateDB.Empty(address) { + gas += params.CallNewAccountGas + } + } else if !evm.StateDB.Exist(address) { + gas += params.CallNewAccountGas + } + if transfersValue { + gas += params.CallValueTransferGas + } + memoryGas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { + return 0, ErrGasUintOverflow + } + + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasCallCode(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + memoryGas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + var ( + gas uint64 + overflow bool + ) + if stack.Back(2).Sign() != 0 { + gas += params.CallValueTransferGas + } + if gas, overflow = math.SafeAdd(gas, memoryGas); overflow { + return 0, ErrGasUintOverflow + } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasDelegateCall(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasStaticCall(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + evm.callGasTemp, err = callGas(evm.chainRules.IsEIP150, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil +} + +func gasSelfdestruct(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var gas uint64 + // EIP150 homestead gas reprice fork: + if evm.chainRules.IsEIP150 { + gas = params.SelfdestructGasEIP150 + var address = common.Address(stack.Back(0).Bytes20()) + + if evm.chainRules.IsEIP158 { + // if empty and transfers value + if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { + gas += params.CreateBySelfdestructGas + } + } else if !evm.StateDB.Exist(address) { + gas += params.CreateBySelfdestructGas + } + } + + if !evm.StateDB.HasSuicided(contract.Address()) { + evm.StateDB.AddRefund(params.SelfdestructRefundGas) + } + return gas, nil +} diff --git a/state/runtime/fakevm/instructions.go b/state/runtime/fakevm/instructions.go new file mode 100644 index 0000000000..f87fd9d6b5 --- /dev/null +++ b/state/runtime/fakevm/instructions.go @@ -0,0 +1,919 @@ +// Copyright 2015 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 fakevm + +import ( + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" +) + +func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Add(&x, y) + return nil, nil +} + +func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Sub(&x, y) + return nil, nil +} + +func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Mul(&x, y) + return nil, nil +} + +func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Div(&x, y) + return nil, nil +} + +func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.SDiv(&x, y) + return nil, nil +} + +func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Mod(&x, y) + return nil, nil +} + +func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.SMod(&x, y) + return nil, nil +} + +func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + base, exponent := scope.Stack.pop(), scope.Stack.peek() + exponent.Exp(&base, exponent) + return nil, nil +} + +func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + back, num := scope.Stack.pop(), scope.Stack.peek() + num.ExtendSign(num, &back) + return nil, nil +} + +func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x := scope.Stack.peek() + x.Not(x) + return nil, nil +} + +func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + if x.Lt(y) { + y.SetOne() + } else { + y.Clear() + } + return nil, nil +} + +func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + if x.Gt(y) { + y.SetOne() + } else { + y.Clear() + } + return nil, nil +} + +func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + if x.Slt(y) { + y.SetOne() + } else { + y.Clear() + } + return nil, nil +} + +func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + if x.Sgt(y) { + y.SetOne() + } else { + y.Clear() + } + return nil, nil +} + +func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + if x.Eq(y) { + y.SetOne() + } else { + y.Clear() + } + return nil, nil +} + +func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x := scope.Stack.peek() + if x.IsZero() { + x.SetOne() + } else { + x.Clear() + } + return nil, nil +} + +func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.And(&x, y) + return nil, nil +} + +func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Or(&x, y) + return nil, nil +} + +func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y := scope.Stack.pop(), scope.Stack.peek() + y.Xor(&x, y) + return nil, nil +} + +func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + th, val := scope.Stack.pop(), scope.Stack.peek() + val.Byte(&th) + return nil, nil +} + +func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() + if z.IsZero() { + z.Clear() + } else { + z.AddMod(&x, &y, z) + } + return nil, nil +} + +func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek() + z.MulMod(&x, &y, z) + return nil, nil +} + +// opSHL implements Shift Left +// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2, +// and pushes on the stack arg2 shifted to the left by arg1 number of bits. +func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards + shift, value := scope.Stack.pop(), scope.Stack.peek() + if shift.LtUint64(256) { + value.Lsh(value, uint(shift.Uint64())) + } else { + value.Clear() + } + return nil, nil +} + +// opSHR implements Logical Shift Right +// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2, +// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill. +func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards + shift, value := scope.Stack.pop(), scope.Stack.peek() + if shift.LtUint64(256) { + value.Rsh(value, uint(shift.Uint64())) + } else { + value.Clear() + } + return nil, nil +} + +// opSAR implements Arithmetic Shift Right +// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2, +// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension. +func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + shift, value := scope.Stack.pop(), scope.Stack.peek() + if shift.GtUint64(256) { + if value.Sign() >= 0 { + value.Clear() + } else { + // Max negative shift: all bits set + value.SetAllOne() + } + return nil, nil + } + n := uint(shift.Uint64()) + value.SRsh(value, n) + return nil, nil +} + +func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + offset, size := scope.Stack.pop(), scope.Stack.peek() + data := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) + + if interpreter.hasher == nil { + interpreter.hasher = crypto.NewKeccakState() + } else { + interpreter.hasher.Reset() + } + interpreter.hasher.Write(data) + interpreter.hasher.Read(interpreter.hasherBuf[:]) + + evm := interpreter.evm + if evm.Config.EnablePreimageRecording { + evm.StateDB.AddPreimage(interpreter.hasherBuf, data) + } + + size.SetBytes(interpreter.hasherBuf[:]) + return nil, nil +} +func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes())) + return nil, nil +} + +func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + slot := scope.Stack.peek() + address := common.Address(slot.Bytes20()) + slot.SetFromBig(interpreter.evm.StateDB.GetBalance(address)) + return nil, nil +} + +func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes())) + return nil, nil +} +func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes())) + return nil, nil +} + +func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v, _ := uint256.FromBig(scope.Contract.value) + scope.Stack.Push(v) + return nil, nil +} + +func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + x := scope.Stack.peek() + if offset, overflow := x.Uint64WithOverflow(); !overflow { + data := getData(scope.Contract.Input, offset, 32) + x.SetBytes(data) + } else { + x.Clear() + } + return nil, nil +} + +func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input)))) + return nil, nil +} + +func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + memOffset = scope.Stack.pop() + dataOffset = scope.Stack.pop() + length = scope.Stack.pop() + ) + dataOffset64, overflow := dataOffset.Uint64WithOverflow() + if overflow { + dataOffset64 = 0xffffffffffffffff + } + // These values are checked for overflow during gas cost calculation + memOffset64 := memOffset.Uint64() + length64 := length.Uint64() + scope.Memory.Set(memOffset64, length64, getData(scope.Contract.Input, dataOffset64, length64)) + + return nil, nil +} + +func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData)))) + return nil, nil +} + +func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + memOffset = scope.Stack.pop() + dataOffset = scope.Stack.pop() + length = scope.Stack.pop() + ) + + offset64, overflow := dataOffset.Uint64WithOverflow() + if overflow { + return nil, ErrReturnDataOutOfBounds + } + // we can reuse dataOffset now (aliasing it for clarity) + var end = dataOffset + end.Add(&dataOffset, &length) + end64, overflow := end.Uint64WithOverflow() + if overflow || uint64(len(interpreter.returnData)) < end64 { + return nil, ErrReturnDataOutOfBounds + } + scope.Memory.Set(memOffset.Uint64(), length.Uint64(), interpreter.returnData[offset64:end64]) + return nil, nil +} + +func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + slot := scope.Stack.peek() + slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20()))) + return nil, nil +} + +func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + l := new(uint256.Int) + l.SetUint64(uint64(len(scope.Contract.Code))) + scope.Stack.Push(l) + return nil, nil +} + +func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + memOffset = scope.Stack.pop() + codeOffset = scope.Stack.pop() + length = scope.Stack.pop() + ) + uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() + if overflow { + uint64CodeOffset = 0xffffffffffffffff + } + codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64()) + scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) + + return nil, nil +} + +func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + stack = scope.Stack + a = stack.pop() + memOffset = stack.pop() + codeOffset = stack.pop() + length = stack.pop() + ) + uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() + if overflow { + uint64CodeOffset = 0xffffffffffffffff + } + addr := common.Address(a.Bytes20()) + codeCopy := getData(interpreter.evm.StateDB.GetCode(addr), uint64CodeOffset, length.Uint64()) + scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) + + return nil, nil +} + +// opExtCodeHash returns the code hash of a specified account. +// There are several cases when the function is called, while we can relay everything +// to `state.GetCodeHash` function to ensure the correctness. +// +// 1. Caller tries to get the code hash of a normal contract account, state +// should return the relative code hash and set it as the result. +// +// 2. Caller tries to get the code hash of a non-existent account, state should +// return common.Hash{} and zero will be set as the result. +// +// 3. Caller tries to get the code hash for an account without contract code, state +// should return emptyCodeHash(0xc5d246...) as the result. +// +// 4. Caller tries to get the code hash of a precompiled account, the result should be +// zero or emptyCodeHash. +// +// It is worth noting that in order to avoid unnecessary create and clean, all precompile +// accounts on mainnet have been transferred 1 wei, so the return here should be +// emptyCodeHash. If the precompile account is not transferred any amount on a private or +// customized chain, the return value will be zero. +// +// 5. Caller tries to get the code hash for an account which is marked as suicided +// in the current transaction, the code hash of this account should be returned. +// +// 6. Caller tries to get the code hash for an account which is marked as deleted, this +// account should be regarded as a non-existent account and zero should be returned. +func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + slot := scope.Stack.peek() + address := common.Address(slot.Bytes20()) + if interpreter.evm.StateDB.Empty(address) { + slot.Clear() + } else { + slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes()) + } + return nil, nil +} + +func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v, _ := uint256.FromBig(interpreter.evm.GasPrice) + scope.Stack.Push(v) + return nil, nil +} + +func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + num := scope.Stack.peek() + num64, overflow := num.Uint64WithOverflow() + if overflow { + num.Clear() + return nil, nil + } + var upper, lower uint64 + upper = interpreter.evm.Context.BlockNumber.Uint64() + if upper < 257 { + lower = 0 + } else { + lower = upper - 256 + } + if num64 >= lower && num64 < upper { + num.SetBytes(interpreter.evm.Context.GetHash(num64).Bytes()) + } else { + num.Clear() + } + return nil, nil +} + +func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes())) + return nil, nil +} + +func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time)) + return nil, nil +} + +func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber) + scope.Stack.Push(v) + return nil, nil +} + +func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty) + scope.Stack.Push(v) + return nil, nil +} + +func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes()) + scope.Stack.Push(v) + return nil, nil +} + +func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit)) + return nil, nil +} + +func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.pop() + return nil, nil +} + +func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + v := scope.Stack.peek() + offset := int64(v.Uint64()) + v.SetBytes(scope.Memory.GetPtr(offset, 32)) + return nil, nil +} + +func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + // pop value of the stack + mStart, val := scope.Stack.pop(), scope.Stack.pop() + scope.Memory.Set32(mStart.Uint64(), &val) + return nil, nil +} + +func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + off, val := scope.Stack.pop(), scope.Stack.pop() + scope.Memory.store[off.Uint64()] = byte(val.Uint64()) + return nil, nil +} + +func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + loc := scope.Stack.peek() + hash := common.Hash(loc.Bytes32()) + val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash) + loc.SetBytes(val.Bytes()) + return nil, nil +} + +func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + loc := scope.Stack.pop() + val := scope.Stack.pop() + interpreter.evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32()) + return nil, nil +} + +func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if atomic.LoadInt32(&interpreter.evm.abort) != 0 { + return nil, errStopToken + } + pos := scope.Stack.pop() + if !scope.Contract.validJumpdest(&pos) { + return nil, ErrInvalidJump + } + *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop + return nil, nil +} + +func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if atomic.LoadInt32(&interpreter.evm.abort) != 0 { + return nil, errStopToken + } + pos, cond := scope.Stack.pop(), scope.Stack.pop() + if !cond.IsZero() { + if !scope.Contract.validJumpdest(&pos) { + return nil, ErrInvalidJump + } + *pc = pos.Uint64() - 1 // pc will be increased by the interpreter loop + } + return nil, nil +} + +func opJumpdest(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + return nil, nil +} + +func opPc(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(*pc)) + return nil, nil +} + +func opMsize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len()))) + return nil, nil +} + +func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.Push(new(uint256.Int).SetUint64(scope.Contract.Gas)) + return nil, nil +} + +func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + var ( + value = scope.Stack.pop() + offset, size = scope.Stack.pop(), scope.Stack.pop() + input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) + gas = scope.Contract.Gas + ) + if interpreter.evm.chainRules.IsEIP150 { + gas -= gas / 64 + } + // reuse size int for stackvalue + stackvalue := size + + scope.Contract.UseGas(gas) + //TODO: use uint256.Int instead of converting with toBig() + var bigVal = big0 + if !value.IsZero() { + bigVal = value.ToBig() + } + + res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, bigVal) + // Push item on the stack based on the returned error. If the ruleset is + // homestead we must check for CodeStoreOutOfGasError (homestead only + // rule) and treat as an error, if the ruleset is frontier we must + // ignore this error and pretend the operation was successful. + if interpreter.evm.chainRules.IsHomestead && suberr == ErrCodeStoreOutOfGas { + stackvalue.Clear() + } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { + stackvalue.Clear() + } else { + stackvalue.SetBytes(addr.Bytes()) + } + scope.Stack.Push(&stackvalue) + scope.Contract.Gas += returnGas + + if suberr == ErrExecutionReverted { + interpreter.returnData = res // set REVERT data to return data buffer + return res, nil + } + interpreter.returnData = nil // clear dirty return data buffer + return nil, nil +} + +func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + var ( + endowment = scope.Stack.pop() + offset, size = scope.Stack.pop(), scope.Stack.pop() + salt = scope.Stack.pop() + input = scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) + gas = scope.Contract.Gas + ) + // Apply EIP150 + gas -= gas / 64 + scope.Contract.UseGas(gas) + // reuse size int for stackvalue + stackvalue := size + //TODO: use uint256.Int instead of converting with toBig() + bigEndowment := big0 + if !endowment.IsZero() { + bigEndowment = endowment.ToBig() + } + res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas, + bigEndowment, &salt) + // Push item on the stack based on the returned error. + if suberr != nil { + stackvalue.Clear() + } else { + stackvalue.SetBytes(addr.Bytes()) + } + scope.Stack.Push(&stackvalue) + scope.Contract.Gas += returnGas + + if suberr == ErrExecutionReverted { + interpreter.returnData = res // set REVERT data to return data buffer + return res, nil + } + interpreter.returnData = nil // clear dirty return data buffer + return nil, nil +} + +func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + stack := scope.Stack + // Pop gas. The actual gas in interpreter.evm.callGasTemp. + // We can use this as a temporary value + temp := stack.pop() + gas := interpreter.evm.callGasTemp + // Pop other call parameters. + addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() + toAddr := common.Address(addr.Bytes20()) + // Get the arguments from the memory. + args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) + + if interpreter.readOnly && !value.IsZero() { + return nil, ErrWriteProtection + } + var bigVal = big0 + //TODO: use uint256.Int instead of converting with toBig() + // By using big0 here, we save an alloc for the most common case (non-ether-transferring contract calls), + // but it would make more sense to extend the usage of uint256.Int + if !value.IsZero() { + gas += params.CallStipend + bigVal = value.ToBig() + } + + ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, bigVal) + + if err != nil { + temp.Clear() + } else { + temp.SetOne() + } + stack.Push(&temp) + if err == nil || err == ErrExecutionReverted { + scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) + } + scope.Contract.Gas += returnGas + + interpreter.returnData = ret + return ret, nil +} + +func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + // Pop gas. The actual gas is in interpreter.evm.callGasTemp. + stack := scope.Stack + // We use it as a temporary value + temp := stack.pop() + gas := interpreter.evm.callGasTemp + // Pop other call parameters. + addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() + toAddr := common.Address(addr.Bytes20()) + // Get arguments from the memory. + args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) + + //TODO: use uint256.Int instead of converting with toBig() + var bigVal = big0 + if !value.IsZero() { + gas += params.CallStipend + bigVal = value.ToBig() + } + + ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, bigVal) + if err != nil { + temp.Clear() + } else { + temp.SetOne() + } + stack.Push(&temp) + if err == nil || err == ErrExecutionReverted { + scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) + } + scope.Contract.Gas += returnGas + + interpreter.returnData = ret + return ret, nil +} + +func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + stack := scope.Stack + // Pop gas. The actual gas is in interpreter.evm.callGasTemp. + // We use it as a temporary value + temp := stack.pop() + gas := interpreter.evm.callGasTemp + // Pop other call parameters. + addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() + toAddr := common.Address(addr.Bytes20()) + // Get arguments from the memory. + args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) + + ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract, toAddr, args, gas) + if err != nil { + temp.Clear() + } else { + temp.SetOne() + } + stack.Push(&temp) + if err == nil || err == ErrExecutionReverted { + scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) + } + scope.Contract.Gas += returnGas + + interpreter.returnData = ret + return ret, nil +} + +func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + // Pop gas. The actual gas is in interpreter.evm.callGasTemp. + stack := scope.Stack + // We use it as a temporary value + temp := stack.pop() + gas := interpreter.evm.callGasTemp + // Pop other call parameters. + addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop() + toAddr := common.Address(addr.Bytes20()) + // Get arguments from the memory. + args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64())) + + ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract, toAddr, args, gas) + if err != nil { + temp.Clear() + } else { + temp.SetOne() + } + stack.Push(&temp) + if err == nil || err == ErrExecutionReverted { + scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) + } + scope.Contract.Gas += returnGas + + interpreter.returnData = ret + return ret, nil +} + +func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + offset, size := scope.Stack.pop(), scope.Stack.pop() + ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) + + return ret, errStopToken +} + +func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + offset, size := scope.Stack.pop(), scope.Stack.pop() + ret := scope.Memory.GetPtr(int64(offset.Uint64()), int64(size.Uint64())) + + interpreter.returnData = ret + return ret, ErrExecutionReverted +} + +func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])} +} + +func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + return nil, errStopToken +} + +func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + beneficiary := scope.Stack.pop() + balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) + interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance) + interpreter.evm.StateDB.Suicide(scope.Contract.Address()) + if interpreter.evm.Config.Debug { + interpreter.evm.Config.Tracer.CaptureEnter(SELFDESTRUCT, scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance) + interpreter.evm.Config.Tracer.CaptureExit([]byte{}, 0, nil) + } + return nil, errStopToken +} + +// following functions are used by the instruction jump table + +// make log instruction function +func makeLog(size int) executionFunc { + return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + if interpreter.readOnly { + return nil, ErrWriteProtection + } + topics := make([]common.Hash, size) + stack := scope.Stack + mStart, mSize := stack.pop(), stack.pop() + for i := 0; i < size; i++ { + addr := stack.pop() + topics[i] = addr.Bytes32() + } + + d := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) + interpreter.evm.StateDB.AddLog(&types.Log{ + Address: scope.Contract.Address(), + Topics: topics, + Data: d, + // This is a non-consensus field, but assigned here because + // core/state doesn't know the current block number. + BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(), + }) + + return nil, nil + } +} + +// opPush1 is a specialized version of pushN +func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + codeLen = uint64(len(scope.Contract.Code)) + integer = new(uint256.Int) + ) + *pc += 1 + if *pc < codeLen { + scope.Stack.Push(integer.SetUint64(uint64(scope.Contract.Code[*pc]))) + } else { + scope.Stack.Push(integer.Clear()) + } + return nil, nil +} + +// make push instruction function +func makePush(size uint64, pushByteSize int) executionFunc { + return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + codeLen := len(scope.Contract.Code) + + startMin := codeLen + if int(*pc+1) < startMin { + startMin = int(*pc + 1) + } + + endMin := codeLen + if startMin+pushByteSize < endMin { + endMin = startMin + pushByteSize + } + + integer := new(uint256.Int) + scope.Stack.Push(integer.SetBytes(common.RightPadBytes( + scope.Contract.Code[startMin:endMin], pushByteSize))) + + *pc += size + return nil, nil + } +} + +// make dup instruction function +func makeDup(size int64) executionFunc { + return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.dup(int(size)) + return nil, nil + } +} + +// make swap instruction function +func makeSwap(size int64) executionFunc { + // switch n + 1 otherwise n would be swapped with n + size++ + return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + scope.Stack.swap(int(size)) + return nil, nil + } +} diff --git a/state/runtime/fakevm/interpreter.go b/state/runtime/fakevm/interpreter.go index cd1984066a..a291b15411 100644 --- a/state/runtime/fakevm/interpreter.go +++ b/state/runtime/fakevm/interpreter.go @@ -1,6 +1,27 @@ +// Copyright 2014 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 fakevm -import "github.com/ethereum/go-ethereum/core/vm" +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" +) // Config are the configuration options for the Interpreter type Config struct { @@ -8,8 +29,212 @@ type Config struct { Tracer EVMLogger // Opcode logger NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls) EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages + ExtraEips []int // Additional EIPS that are to be enabled +} + +// ScopeContext contains the things that are per-call, such as stack and memory, +// but not transients like pc and gas +type ScopeContext struct { + Memory *Memory + Stack *Stack + Contract *Contract +} + +// EVMInterpreter represents an EVM interpreter +type EVMInterpreter struct { + evm *FakeEVM + table *JumpTable + + hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes + hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes + + readOnly bool // Whether to throw on stateful modifications + returnData []byte // Last CALL's return data for subsequent reuse +} + +// NewEVMInterpreter returns a new instance of the Interpreter. +func NewEVMInterpreter(evm *FakeEVM) *EVMInterpreter { + // If jump table was not initialised we set the default one. + var table *JumpTable + switch { + case evm.chainRules.IsShanghai: + table = &shanghaiInstructionSet + case evm.chainRules.IsMerge: + table = &mergeInstructionSet + case evm.chainRules.IsLondon: + table = &londonInstructionSet + case evm.chainRules.IsBerlin: + table = &berlinInstructionSet + case evm.chainRules.IsIstanbul: + table = &istanbulInstructionSet + case evm.chainRules.IsConstantinople: + table = &constantinopleInstructionSet + case evm.chainRules.IsByzantium: + table = &byzantiumInstructionSet + case evm.chainRules.IsEIP158: + table = &spuriousDragonInstructionSet + case evm.chainRules.IsEIP150: + table = &tangerineWhistleInstructionSet + case evm.chainRules.IsHomestead: + table = &homesteadInstructionSet + default: + table = &frontierInstructionSet + } + var extraEips []int + if len(evm.Config.ExtraEips) > 0 { + // Deep-copy jumptable to prevent modification of opcodes in other tables + table = copyJumpTable(table) + } + for _, eip := range evm.Config.ExtraEips { + if err := EnableEIP(eip, table); err != nil { + // Disable it, so caller can check if it's activated or not + log.Error("EIP activation failed", "eip", eip, "error", err) + } else { + extraEips = append(extraEips, eip) + } + } + evm.Config.ExtraEips = extraEips + return &EVMInterpreter{evm: evm, table: table} +} + +// Run loops and evaluates the contract's code with the given input data and returns +// the return byte-slice and an error if one occurred. +// +// It's important to note that any errors returned by the interpreter should be +// considered a revert-and-consume-all-gas operation except for +// ErrExecutionReverted which means revert-and-keep-gas-left. +func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { + // Increment the call depth which is restricted to 1024 + in.evm.depth++ + defer func() { in.evm.depth-- }() + + // Make sure the readOnly is only set if we aren't in readOnly yet. + // This also makes sure that the readOnly flag isn't removed for child calls. + if readOnly && !in.readOnly { + in.readOnly = true + defer func() { in.readOnly = false }() + } + + // Reset the previous call's return data. It's unimportant to preserve the old buffer + // as every returning call will return new data anyway. + in.returnData = nil + + // Don't bother with the execution if there's no code. + if len(contract.Code) == 0 { + return nil, nil + } + + var ( + op OpCode // current opcode + mem = NewMemory() // bound memory + stack = NewStack() // local stack + callContext = &ScopeContext{ + Memory: mem, + Stack: stack, + Contract: contract, + } + // For optimisation reason we're using uint64 as the program counter. + // It's theoretically possible to go above 2^64. The YP defines the PC + // to be uint256. Practically much less so feasible. + pc = uint64(0) // program counter + cost uint64 + // copies used by tracer + pcCopy uint64 // needed for the deferred EVMLogger + gasCopy uint64 // for EVMLogger to log gas remaining before execution + logged bool // deferred EVMLogger should ignore already logged steps + res []byte // result of the opcode execution function + ) + // Don't move this deferred function, it's placed before the capturestate-deferred method, + // so that it get's executed _after_: the capturestate needs the stacks before + // they are returned to the pools + defer func() { + returnStack(stack) + }() + contract.Input = input + + if in.evm.Config.Debug { + defer func() { + if err != nil { + if !logged { + in.evm.Config.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err) + } else { + in.evm.Config.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err) + } + } + }() + } + // The Interpreter main run loop (contextual). This loop runs until either an + // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during + // the execution of one of the operations or until the done flag is set by the + // parent context. + for { + if in.evm.Config.Debug { + // Capture pre-execution values for tracing. + logged, pcCopy, gasCopy = false, pc, contract.Gas + } + // Get the operation from the jump table and validate the stack to ensure there are + // enough stack items available to perform the operation. + op = contract.GetOp(pc) + operation := in.table[op] + cost = operation.constantGas // For tracing + // Validate stack + if sLen := stack.len(); sLen < operation.minStack { + return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} + } else if sLen > operation.maxStack { + return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} + } + if !contract.UseGas(cost) { + return nil, ErrOutOfGas + } + if operation.dynamicGas != nil { + // All ops with a dynamic memory usage also has a dynamic gas cost. + var memorySize uint64 + // calculate the new memory size and expand the memory to fit + // the operation + // Memory check needs to be done prior to evaluating the dynamic gas portion, + // to detect calculation overflows + if operation.memorySize != nil { + memSize, overflow := operation.memorySize(stack) + if overflow { + return nil, ErrGasUintOverflow + } + // memory is expanded in words of 32 bytes. Gas + // is also calculated in words. + if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { + return nil, ErrGasUintOverflow + } + } + // Consume the gas and return an error if not enough gas is available. + // cost is explicitly set so that the capture state defer method can get the proper cost + var dynamicCost uint64 + dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize) + cost += dynamicCost // for tracing + if err != nil || !contract.UseGas(dynamicCost) { + return nil, ErrOutOfGas + } + // Do tracing before memory expansion + if in.evm.Config.Debug { + in.evm.Config.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err) + logged = true + } + if memorySize > 0 { + mem.Resize(memorySize) + } + } else if in.evm.Config.Debug { + in.evm.Config.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err) + logged = true + } + // execute the operation + res, err = operation.execute(&pc, in, callContext) + if err != nil { + break + } + pc++ + } - JumpTable *vm.JumpTable // EVM instruction table, automatically populated if unset + if err == errStopToken { + err = nil // clear stop token error + } - ExtraEips []int // Additional EIPS that are to be enabled + return res, err } diff --git a/state/runtime/fakevm/jump_table.go b/state/runtime/fakevm/jump_table.go new file mode 100644 index 0000000000..ba3aa98a89 --- /dev/null +++ b/state/runtime/fakevm/jump_table.go @@ -0,0 +1,1064 @@ +// Copyright 2015 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 fakevm + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/params" +) + +type ( + executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) + gasFunc func(*FakeEVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64 + // memorySizeFunc returns the required size, and whether the operation overflowed a uint64 + memorySizeFunc func(*Stack) (size uint64, overflow bool) +) + +type operation struct { + // execute is the operation function + execute executionFunc + constantGas uint64 + dynamicGas gasFunc + // minStack tells how many stack items are required + minStack int + // maxStack specifies the max length the stack can have for this operation + // to not overflow the stack. + maxStack int + + // memorySize returns the memory size required for the operation + memorySize memorySizeFunc +} + +var ( + frontierInstructionSet = newFrontierInstructionSet() + homesteadInstructionSet = newHomesteadInstructionSet() + tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet() + spuriousDragonInstructionSet = newSpuriousDragonInstructionSet() + byzantiumInstructionSet = newByzantiumInstructionSet() + constantinopleInstructionSet = newConstantinopleInstructionSet() + istanbulInstructionSet = newIstanbulInstructionSet() + berlinInstructionSet = newBerlinInstructionSet() + londonInstructionSet = newLondonInstructionSet() + mergeInstructionSet = newMergeInstructionSet() + shanghaiInstructionSet = newShanghaiInstructionSet() +) + +// JumpTable contains the EVM opcodes supported at a given fork. +type JumpTable [256]*operation + +func validate(jt JumpTable) JumpTable { + for i, op := range jt { + if op == nil { + panic(fmt.Sprintf("op %#x is not set", i)) + } + // The interpreter has an assumption that if the memorySize function is + // set, then the dynamicGas function is also set. This is a somewhat + // arbitrary assumption, and can be removed if we need to -- but it + // allows us to avoid a condition check. As long as we have that assumption + // in there, this little sanity check prevents us from merging in a + // change which violates it. + if op.memorySize != nil && op.dynamicGas == nil { + panic(fmt.Sprintf("op %v has dynamic memory but not dynamic gas", OpCode(i).String())) + } + } + return jt +} + +func newShanghaiInstructionSet() JumpTable { + instructionSet := newMergeInstructionSet() + enable3855(&instructionSet) // PUSH0 instruction + enable3860(&instructionSet) // Limit and meter initcode + return validate(instructionSet) +} + +func newMergeInstructionSet() JumpTable { + instructionSet := newLondonInstructionSet() + instructionSet[PREVRANDAO] = &operation{ + execute: opRandom, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } + return validate(instructionSet) +} + +// newLondonInstructionSet returns the frontier, homestead, byzantium, +// constantinople, istanbul, petersburg, berlin and london instructions. +func newLondonInstructionSet() JumpTable { + instructionSet := newBerlinInstructionSet() + enable3529(&instructionSet) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529 + enable3198(&instructionSet) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198 + return validate(instructionSet) +} + +// newBerlinInstructionSet returns the frontier, homestead, byzantium, +// constantinople, istanbul, petersburg and berlin instructions. +func newBerlinInstructionSet() JumpTable { + instructionSet := newIstanbulInstructionSet() + enable2929(&instructionSet) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929 + return validate(instructionSet) +} + +// newIstanbulInstructionSet returns the frontier, homestead, byzantium, +// constantinople, istanbul and petersburg instructions. +func newIstanbulInstructionSet() JumpTable { + instructionSet := newConstantinopleInstructionSet() + + enable1344(&instructionSet) // ChainID opcode - https://eips.ethereum.org/EIPS/eip-1344 + enable1884(&instructionSet) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884 + enable2200(&instructionSet) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200 + + return validate(instructionSet) +} + +// newConstantinopleInstructionSet returns the frontier, homestead, +// byzantium and constantinople instructions. +func newConstantinopleInstructionSet() JumpTable { + instructionSet := newByzantiumInstructionSet() + instructionSet[SHL] = &operation{ + execute: opSHL, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + } + instructionSet[SHR] = &operation{ + execute: opSHR, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + } + instructionSet[SAR] = &operation{ + execute: opSAR, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + } + instructionSet[EXTCODEHASH] = &operation{ + execute: opExtCodeHash, + constantGas: params.ExtcodeHashGasConstantinople, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + } + instructionSet[CREATE2] = &operation{ + execute: opCreate2, + constantGas: params.Create2Gas, + dynamicGas: gasCreate2, + minStack: minStack(4, 1), + maxStack: maxStack(4, 1), + memorySize: memoryCreate2, + } + return validate(instructionSet) +} + +// newByzantiumInstructionSet returns the frontier, homestead and +// byzantium instructions. +func newByzantiumInstructionSet() JumpTable { + instructionSet := newSpuriousDragonInstructionSet() + instructionSet[STATICCALL] = &operation{ + execute: opStaticCall, + constantGas: params.CallGasEIP150, + dynamicGas: gasStaticCall, + minStack: minStack(6, 1), + maxStack: maxStack(6, 1), + memorySize: memoryStaticCall, + } + instructionSet[RETURNDATASIZE] = &operation{ + execute: opReturnDataSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + } + instructionSet[RETURNDATACOPY] = &operation{ + execute: opReturnDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasReturnDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryReturnDataCopy, + } + instructionSet[REVERT] = &operation{ + execute: opRevert, + dynamicGas: gasRevert, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryRevert, + } + return validate(instructionSet) +} + +// EIP 158 a.k.a Spurious Dragon +func newSpuriousDragonInstructionSet() JumpTable { + instructionSet := newTangerineWhistleInstructionSet() + instructionSet[EXP].dynamicGas = gasExpEIP158 + return validate(instructionSet) +} + +// EIP 150 a.k.a Tangerine Whistle +func newTangerineWhistleInstructionSet() JumpTable { + instructionSet := newHomesteadInstructionSet() + instructionSet[BALANCE].constantGas = params.BalanceGasEIP150 + instructionSet[EXTCODESIZE].constantGas = params.ExtcodeSizeGasEIP150 + instructionSet[SLOAD].constantGas = params.SloadGasEIP150 + instructionSet[EXTCODECOPY].constantGas = params.ExtcodeCopyBaseEIP150 + instructionSet[CALL].constantGas = params.CallGasEIP150 + instructionSet[CALLCODE].constantGas = params.CallGasEIP150 + instructionSet[DELEGATECALL].constantGas = params.CallGasEIP150 + return validate(instructionSet) +} + +// newHomesteadInstructionSet returns the frontier and homestead +// instructions that can be executed during the homestead phase. +func newHomesteadInstructionSet() JumpTable { + instructionSet := newFrontierInstructionSet() + instructionSet[DELEGATECALL] = &operation{ + execute: opDelegateCall, + dynamicGas: gasDelegateCall, + constantGas: params.CallGasFrontier, + minStack: minStack(6, 1), + maxStack: maxStack(6, 1), + memorySize: memoryDelegateCall, + } + return validate(instructionSet) +} + +// newFrontierInstructionSet returns the frontier instructions +// that can be executed during the frontier phase. +func newFrontierInstructionSet() JumpTable { + tbl := JumpTable{ + STOP: { + execute: opStop, + constantGas: 0, + minStack: minStack(0, 0), + maxStack: maxStack(0, 0), + }, + ADD: { + execute: opAdd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + MUL: { + execute: opMul, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SUB: { + execute: opSub, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + DIV: { + execute: opDiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SDIV: { + execute: opSdiv, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + MOD: { + execute: opMod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SMOD: { + execute: opSmod, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + ADDMOD: { + execute: opAddmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + }, + MULMOD: { + execute: opMulmod, + constantGas: GasMidStep, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + }, + EXP: { + execute: opExp, + dynamicGas: gasExpFrontier, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SIGNEXTEND: { + execute: opSignExtend, + constantGas: GasFastStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + LT: { + execute: opLt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + GT: { + execute: opGt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SLT: { + execute: opSlt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + SGT: { + execute: opSgt, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + EQ: { + execute: opEq, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + ISZERO: { + execute: opIszero, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + AND: { + execute: opAnd, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + XOR: { + execute: opXor, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + OR: { + execute: opOr, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + NOT: { + execute: opNot, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + BYTE: { + execute: opByte, + constantGas: GasFastestStep, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + }, + KECCAK256: { + execute: opKeccak256, + constantGas: params.Keccak256Gas, + dynamicGas: gasKeccak256, + minStack: minStack(2, 1), + maxStack: maxStack(2, 1), + memorySize: memoryKeccak256, + }, + ADDRESS: { + execute: opAddress, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + BALANCE: { + execute: opBalance, + constantGas: params.BalanceGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + ORIGIN: { + execute: opOrigin, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + CALLER: { + execute: opCaller, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + CALLVALUE: { + execute: opCallValue, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + CALLDATALOAD: { + execute: opCallDataLoad, + constantGas: GasFastestStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + CALLDATASIZE: { + execute: opCallDataSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + CALLDATACOPY: { + execute: opCallDataCopy, + constantGas: GasFastestStep, + dynamicGas: gasCallDataCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCallDataCopy, + }, + CODESIZE: { + execute: opCodeSize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + CODECOPY: { + execute: opCodeCopy, + constantGas: GasFastestStep, + dynamicGas: gasCodeCopy, + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryCodeCopy, + }, + GASPRICE: { + execute: opGasprice, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + EXTCODESIZE: { + execute: opExtCodeSize, + constantGas: params.ExtcodeSizeGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + EXTCODECOPY: { + execute: opExtCodeCopy, + constantGas: params.ExtcodeCopyBaseFrontier, + dynamicGas: gasExtCodeCopy, + minStack: minStack(4, 0), + maxStack: maxStack(4, 0), + memorySize: memoryExtCodeCopy, + }, + BLOCKHASH: { + execute: opBlockhash, + constantGas: GasExtStep, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + COINBASE: { + execute: opCoinbase, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + TIMESTAMP: { + execute: opTimestamp, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + NUMBER: { + execute: opNumber, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + DIFFICULTY: { + execute: opDifficulty, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + GASLIMIT: { + execute: opGasLimit, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + POP: { + execute: opPop, + constantGas: GasQuickStep, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + }, + MLOAD: { + execute: opMload, + constantGas: GasFastestStep, + dynamicGas: gasMLoad, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + memorySize: memoryMLoad, + }, + MSTORE: { + execute: opMstore, + constantGas: GasFastestStep, + dynamicGas: gasMStore, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryMStore, + }, + MSTORE8: { + execute: opMstore8, + constantGas: GasFastestStep, + dynamicGas: gasMStore8, + memorySize: memoryMStore8, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + }, + SLOAD: { + execute: opSload, + constantGas: params.SloadGasFrontier, + minStack: minStack(1, 1), + maxStack: maxStack(1, 1), + }, + SSTORE: { + execute: opSstore, + dynamicGas: gasSStore, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + }, + JUMP: { + execute: opJump, + constantGas: GasMidStep, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + }, + JUMPI: { + execute: opJumpi, + constantGas: GasSlowStep, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + }, + PC: { + execute: opPc, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + MSIZE: { + execute: opMsize, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + GAS: { + execute: opGas, + constantGas: GasQuickStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + JUMPDEST: { + execute: opJumpdest, + constantGas: params.JumpdestGas, + minStack: minStack(0, 0), + maxStack: maxStack(0, 0), + }, + PUSH1: { + execute: opPush1, + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH2: { + execute: makePush(2, 2), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH3: { + execute: makePush(3, 3), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH4: { + execute: makePush(4, 4), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH5: { + execute: makePush(5, 5), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH6: { + execute: makePush(6, 6), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH7: { + execute: makePush(7, 7), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH8: { + execute: makePush(8, 8), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH9: { + execute: makePush(9, 9), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH10: { + execute: makePush(10, 10), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH11: { + execute: makePush(11, 11), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH12: { + execute: makePush(12, 12), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH13: { + execute: makePush(13, 13), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH14: { + execute: makePush(14, 14), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH15: { + execute: makePush(15, 15), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH16: { + execute: makePush(16, 16), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH17: { + execute: makePush(17, 17), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH18: { + execute: makePush(18, 18), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH19: { + execute: makePush(19, 19), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH20: { + execute: makePush(20, 20), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH21: { + execute: makePush(21, 21), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH22: { + execute: makePush(22, 22), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH23: { + execute: makePush(23, 23), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH24: { + execute: makePush(24, 24), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH25: { + execute: makePush(25, 25), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH26: { + execute: makePush(26, 26), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH27: { + execute: makePush(27, 27), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH28: { + execute: makePush(28, 28), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH29: { + execute: makePush(29, 29), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH30: { + execute: makePush(30, 30), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH31: { + execute: makePush(31, 31), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + PUSH32: { + execute: makePush(32, 32), + constantGas: GasFastestStep, + minStack: minStack(0, 1), + maxStack: maxStack(0, 1), + }, + DUP1: { + execute: makeDup(1), + constantGas: GasFastestStep, + minStack: minDupStack(1), + maxStack: maxDupStack(1), + }, + DUP2: { + execute: makeDup(2), + constantGas: GasFastestStep, + minStack: minDupStack(2), + maxStack: maxDupStack(2), + }, + DUP3: { + execute: makeDup(3), + constantGas: GasFastestStep, + minStack: minDupStack(3), + maxStack: maxDupStack(3), + }, + DUP4: { + execute: makeDup(4), + constantGas: GasFastestStep, + minStack: minDupStack(4), + maxStack: maxDupStack(4), + }, + DUP5: { + execute: makeDup(5), + constantGas: GasFastestStep, + minStack: minDupStack(5), + maxStack: maxDupStack(5), + }, + DUP6: { + execute: makeDup(6), + constantGas: GasFastestStep, + minStack: minDupStack(6), + maxStack: maxDupStack(6), + }, + DUP7: { + execute: makeDup(7), + constantGas: GasFastestStep, + minStack: minDupStack(7), + maxStack: maxDupStack(7), + }, + DUP8: { + execute: makeDup(8), + constantGas: GasFastestStep, + minStack: minDupStack(8), + maxStack: maxDupStack(8), + }, + DUP9: { + execute: makeDup(9), + constantGas: GasFastestStep, + minStack: minDupStack(9), + maxStack: maxDupStack(9), + }, + DUP10: { + execute: makeDup(10), + constantGas: GasFastestStep, + minStack: minDupStack(10), + maxStack: maxDupStack(10), + }, + DUP11: { + execute: makeDup(11), + constantGas: GasFastestStep, + minStack: minDupStack(11), + maxStack: maxDupStack(11), + }, + DUP12: { + execute: makeDup(12), + constantGas: GasFastestStep, + minStack: minDupStack(12), + maxStack: maxDupStack(12), + }, + DUP13: { + execute: makeDup(13), + constantGas: GasFastestStep, + minStack: minDupStack(13), + maxStack: maxDupStack(13), + }, + DUP14: { + execute: makeDup(14), + constantGas: GasFastestStep, + minStack: minDupStack(14), + maxStack: maxDupStack(14), + }, + DUP15: { + execute: makeDup(15), + constantGas: GasFastestStep, + minStack: minDupStack(15), + maxStack: maxDupStack(15), + }, + DUP16: { + execute: makeDup(16), + constantGas: GasFastestStep, + minStack: minDupStack(16), + maxStack: maxDupStack(16), + }, + SWAP1: { + execute: makeSwap(1), + constantGas: GasFastestStep, + minStack: minSwapStack(2), + maxStack: maxSwapStack(2), + }, + SWAP2: { + execute: makeSwap(2), + constantGas: GasFastestStep, + minStack: minSwapStack(3), + maxStack: maxSwapStack(3), + }, + SWAP3: { + execute: makeSwap(3), + constantGas: GasFastestStep, + minStack: minSwapStack(4), + maxStack: maxSwapStack(4), + }, + SWAP4: { + execute: makeSwap(4), + constantGas: GasFastestStep, + minStack: minSwapStack(5), + maxStack: maxSwapStack(5), + }, + SWAP5: { + execute: makeSwap(5), + constantGas: GasFastestStep, + minStack: minSwapStack(6), + maxStack: maxSwapStack(6), + }, + SWAP6: { + execute: makeSwap(6), + constantGas: GasFastestStep, + minStack: minSwapStack(7), + maxStack: maxSwapStack(7), + }, + SWAP7: { + execute: makeSwap(7), + constantGas: GasFastestStep, + minStack: minSwapStack(8), + maxStack: maxSwapStack(8), + }, + SWAP8: { + execute: makeSwap(8), + constantGas: GasFastestStep, + minStack: minSwapStack(9), + maxStack: maxSwapStack(9), + }, + SWAP9: { + execute: makeSwap(9), + constantGas: GasFastestStep, + minStack: minSwapStack(10), + maxStack: maxSwapStack(10), + }, + SWAP10: { + execute: makeSwap(10), + constantGas: GasFastestStep, + minStack: minSwapStack(11), + maxStack: maxSwapStack(11), + }, + SWAP11: { + execute: makeSwap(11), + constantGas: GasFastestStep, + minStack: minSwapStack(12), + maxStack: maxSwapStack(12), + }, + SWAP12: { + execute: makeSwap(12), + constantGas: GasFastestStep, + minStack: minSwapStack(13), + maxStack: maxSwapStack(13), + }, + SWAP13: { + execute: makeSwap(13), + constantGas: GasFastestStep, + minStack: minSwapStack(14), + maxStack: maxSwapStack(14), + }, + SWAP14: { + execute: makeSwap(14), + constantGas: GasFastestStep, + minStack: minSwapStack(15), + maxStack: maxSwapStack(15), + }, + SWAP15: { + execute: makeSwap(15), + constantGas: GasFastestStep, + minStack: minSwapStack(16), + maxStack: maxSwapStack(16), + }, + SWAP16: { + execute: makeSwap(16), + constantGas: GasFastestStep, + minStack: minSwapStack(17), + maxStack: maxSwapStack(17), + }, + LOG0: { + execute: makeLog(0), + dynamicGas: makeGasLog(0), + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryLog, + }, + LOG1: { + execute: makeLog(1), + dynamicGas: makeGasLog(1), + minStack: minStack(3, 0), + maxStack: maxStack(3, 0), + memorySize: memoryLog, + }, + LOG2: { + execute: makeLog(2), + dynamicGas: makeGasLog(2), + minStack: minStack(4, 0), + maxStack: maxStack(4, 0), + memorySize: memoryLog, + }, + LOG3: { + execute: makeLog(3), + dynamicGas: makeGasLog(3), + minStack: minStack(5, 0), + maxStack: maxStack(5, 0), + memorySize: memoryLog, + }, + LOG4: { + execute: makeLog(4), + dynamicGas: makeGasLog(4), + minStack: minStack(6, 0), + maxStack: maxStack(6, 0), + memorySize: memoryLog, + }, + CREATE: { + execute: opCreate, + constantGas: params.CreateGas, + dynamicGas: gasCreate, + minStack: minStack(3, 1), + maxStack: maxStack(3, 1), + memorySize: memoryCreate, + }, + CALL: { + execute: opCall, + constantGas: params.CallGasFrontier, + dynamicGas: gasCall, + minStack: minStack(7, 1), + maxStack: maxStack(7, 1), + memorySize: memoryCall, + }, + CALLCODE: { + execute: opCallCode, + constantGas: params.CallGasFrontier, + dynamicGas: gasCallCode, + minStack: minStack(7, 1), + maxStack: maxStack(7, 1), + memorySize: memoryCall, + }, + RETURN: { + execute: opReturn, + dynamicGas: gasReturn, + minStack: minStack(2, 0), + maxStack: maxStack(2, 0), + memorySize: memoryReturn, + }, + SELFDESTRUCT: { + execute: opSelfdestruct, + dynamicGas: gasSelfdestruct, + minStack: minStack(1, 0), + maxStack: maxStack(1, 0), + }, + } + + // Fill all unassigned slots with opUndefined. + for i, entry := range tbl { + if entry == nil { + tbl[i] = &operation{execute: opUndefined, maxStack: maxStack(0, 0)} + } + } + + return validate(tbl) +} + +func copyJumpTable(source *JumpTable) *JumpTable { + dest := *source + for i, op := range source { + if op != nil { + opCopy := *op + dest[i] = &opCopy + } + } + return &dest +} diff --git a/state/runtime/fakevm/logger.go b/state/runtime/fakevm/logger.go index cfd316d6dc..3595c003ad 100644 --- a/state/runtime/fakevm/logger.go +++ b/state/runtime/fakevm/logger.go @@ -1,4 +1,4 @@ -// Copyright 2021 The go-ethereum Authors +// Copyright 2015 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 @@ -18,10 +18,8 @@ package fakevm import ( "math/big" - "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" ) // EVMLogger is used to collect execution traces from an EVM transaction @@ -35,11 +33,11 @@ type EVMLogger interface { CaptureTxEnd(restGas uint64) // Top call frame CaptureStart(env *FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) - CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) + CaptureEnd(output []byte, gasUsed uint64, err error) // Rest of call frames - CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) + CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) CaptureExit(output []byte, gasUsed uint64, err error) // Opcode level - CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) - CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) + CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) + CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) } diff --git a/state/runtime/fakevm/memory.go b/state/runtime/fakevm/memory.go index e7453e4ef5..e88ef80152 100644 --- a/state/runtime/fakevm/memory.go +++ b/state/runtime/fakevm/memory.go @@ -17,14 +17,13 @@ package fakevm import ( - "fmt" - "github.com/holiman/uint256" ) // Memory implements a simple memory model for the ethereum virtual machine. type Memory struct { - store []byte + store []byte + lastGasCost uint64 } // NewMemory returns a new memory model. @@ -54,10 +53,9 @@ func (m *Memory) Set32(offset uint64, val *uint256.Int) { if offset+32 > uint64(len(m.store)) { panic("invalid memory: store empty") } - // Zero the memory area - copy(m.store[offset:offset+32], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) // Fill in relevant bits - val.WriteToSlice(m.store[offset:]) + b32 := val.Bytes32() + copy(m.store[offset:], b32[:]) } // Resize resizes the memory to size @@ -105,18 +103,3 @@ func (m *Memory) Len() int { func (m *Memory) Data() []byte { return m.store } - -// Print dumps the content of the memory. -func (m *Memory) Print() { - fmt.Printf("### mem %d bytes ###\n", len(m.store)) - if len(m.store) > 0 { - addr := 0 - for i := 0; i+32 <= len(m.store); i += 32 { - fmt.Printf("%03d: % x\n", addr, m.store[i:i+32]) - addr++ - } - } else { - fmt.Println("-- empty --") - } - fmt.Println("####################") -} diff --git a/state/runtime/fakevm/memory_table.go b/state/runtime/fakevm/memory_table.go new file mode 100644 index 0000000000..7f9221b1c3 --- /dev/null +++ b/state/runtime/fakevm/memory_table.go @@ -0,0 +1,113 @@ +// Copyright 2017 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 fakevm + +func memoryKeccak256(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) +} + +func memoryCallDataCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) +} + +func memoryReturnDataCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) +} + +func memoryCodeCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(2)) +} + +func memoryExtCodeCopy(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(3)) +} + +func memoryMLoad(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 32) +} + +func memoryMStore8(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 1) +} + +func memoryMStore(stack *Stack) (uint64, bool) { + return calcMemSize64WithUint(stack.Back(0), 32) +} + +func memoryCreate(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(2)) +} + +func memoryCreate2(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(1), stack.Back(2)) +} + +func memoryCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(5), stack.Back(6)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(3), stack.Back(4)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false +} +func memoryDelegateCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(2), stack.Back(3)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false +} + +func memoryStaticCall(stack *Stack) (uint64, bool) { + x, overflow := calcMemSize64(stack.Back(4), stack.Back(5)) + if overflow { + return 0, true + } + y, overflow := calcMemSize64(stack.Back(2), stack.Back(3)) + if overflow { + return 0, true + } + if x > y { + return x, false + } + return y, false +} + +func memoryReturn(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) +} + +func memoryRevert(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) +} + +func memoryLog(stack *Stack) (uint64, bool) { + return calcMemSize64(stack.Back(0), stack.Back(1)) +} diff --git a/state/runtime/fakevm/opcodes.go b/state/runtime/fakevm/opcodes.go index 844f397216..a1ba2c7271 100644 --- a/state/runtime/fakevm/opcodes.go +++ b/state/runtime/fakevm/opcodes.go @@ -1,465 +1,266 @@ +// Copyright 2014 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 fakevm -// Ethereum Virtual Machine OpCode s -// https://ethervm.io/#opcodes +import ( + "fmt" +) -// OpCode is the EVM opcode +// OpCode is an EVM opcode type OpCode byte -const ( - - // STOP halts execution of the contract - STOP = 0x00 - - // ADD performs (u)int256 addition modulo 2**256 - ADD = 0x01 - - // MUL performs (u)int256 multiplication modulo 2**256 - MUL = 0x02 - - // SUB performs (u)int256 subtraction modulo 2**256 - SUB = 0x03 - - // DIV performs uint256 division - DIV = 0x04 - - // SDIV performs int256 division - SDIV = 0x05 - - // MOD performs uint256 modulus - MOD = 0x06 - - // SMOD performs int256 modulus - SMOD = 0x07 - - // ADDMOD performs (u)int256 addition modulo N - ADDMOD = 0x08 - - // MULMOD performs (u)int256 multiplication modulo N - MULMOD = 0x09 - - // EXP performs uint256 exponentiation modulo 2**256 - EXP = 0x0A - - // SIGNEXTEND performs sign extends x from (b + 1) * 8 bits to 256 bits. - SIGNEXTEND = 0x0B - - // LT performs int256 comparison - LT = 0x10 - - // GT performs int256 comparison - GT = 0x11 - - // SLT performs int256 comparison - SLT = 0x12 - - // SGT performs int256 comparison - SGT = 0x13 - - // EQ performs (u)int256 equality - EQ = 0x14 - - // ISZERO checks if (u)int256 is zero - ISZERO = 0x15 - - // AND performs 256-bit bitwise and - AND = 0x16 - - // OR performs 256-bit bitwise or - OR = 0x17 - - // XOR performs 256-bit bitwise xor - XOR = 0x18 - - // NOT performs 256-bit bitwise not - NOT = 0x19 - - // BYTE returns the ith byte of (u)int256 x counting from most significant byte - BYTE = 0x1A - - // SHL performs a shift left - SHL = 0x1B - - // SHR performs a logical shift right - SHR = 0x1C - - // SAR performs an arithmetic shift right - SAR = 0x1D - - // SHA3 performs the keccak256 hash function - SHA3 = 0x20 - - // ADDRESS returns the address of the executing contract - ADDRESS = 0x30 - - // BALANCE returns the address balance in wei - BALANCE = 0x31 - - // ORIGIN returns the transaction origin address - ORIGIN = 0x32 - - // CALLER returns the message caller address - CALLER = 0x33 - - // CALLVALUE returns the message funds in wei - CALLVALUE = 0x34 - - // CALLDATALOAD reads a (u)int256 from message data - CALLDATALOAD = 0x35 - - // CALLDATASIZE returns the message data length in bytes - CALLDATASIZE = 0x36 - - // CALLDATACOPY copies the message data - CALLDATACOPY = 0x37 - - // CODESIZE returns the length of the executing contract's code in bytes - CODESIZE = 0x38 - - // CODECOPY copies the executing contract bytecode - CODECOPY = 0x39 - - // GASPRICE returns the gas price of the executing transaction, in wei per unit of gas - GASPRICE = 0x3A - - // EXTCODESIZE returns the length of the contract bytecode at addr - EXTCODESIZE = 0x3B - - // EXTCODECOPY copies the contract bytecode - EXTCODECOPY = 0x3C - - // RETURNDATASIZE returns the size of the returned data from the last external call in bytes - RETURNDATASIZE = 0x3D - - // RETURNDATACOPY copies the returned data - RETURNDATACOPY = 0x3E - - // EXTCODEHASH returns the hash of the specified contract bytecode - EXTCODEHASH = 0x3F - - // BLOCKHASH returns the hash of the specific block. Only valid for the last 256 most recent blocks - BLOCKHASH = 0x40 - - // COINBASE returns the address of the current block's miner - COINBASE = 0x41 - - // TIMESTAMP returns the current block's Unix timestamp in seconds - TIMESTAMP = 0x42 - - // NUMBER returns the current block's number - NUMBER = 0x43 - - // DIFFICULTY returns the current block's difficulty - DIFFICULTY = 0x44 - - // GASLIMIT returns the current block's gas limit - GASLIMIT = 0x45 - - // CHAINID returns the id of the chain - CHAINID = 0x46 - - // SELFBALANCE returns the balance of the current account - SELFBALANCE = 0x47 - - // POP pops a (u)int256 off the stack and discards it - POP = 0x50 - - // MLOAD reads a (u)int256 from memory - MLOAD = 0x51 - - // MSTORE writes a (u)int256 to memory - MSTORE = 0x52 - - // MSTORE8 writes a uint8 to memory - MSTORE8 = 0x53 - - // SLOAD reads a (u)int256 from storage - SLOAD = 0x54 - - // SSTORE writes a (u)int256 to storage - SSTORE = 0x55 - - // JUMP performs an unconditional jump - JUMP = 0x56 - - // JUMPI performs a conditional jump if condition is truthy - JUMPI = 0x57 - - // PC returns the program counter - PC = 0x58 - - // MSIZE returns the size of memory for this contract execution, in bytes - MSIZE = 0x59 - - // GAS returns the remaining gas - GAS = 0x5A - - // JUMPDEST corresponds to a possible jump destination - JUMPDEST = 0x5B - - // PUSH1 pushes a 1-byte value onto the stack - PUSH1 = 0x60 - - // PUSH2 pushes a 2-bytes value onto the stack - PUSH2 = 0x61 - - // PUSH3 pushes a 3-bytes value onto the stack - PUSH3 = 0x62 - - // PUSH4 pushes a 4-bytes value onto the stack - PUSH4 = 0x63 - - // PUSH5 pushes a 5-bytes value onto the stack - PUSH5 = 0x64 - - // PUSH6 pushes a 6-bytes value onto the stack - PUSH6 = 0x65 - - // PUSH7 pushes a 7-bytes value onto the stack - PUSH7 = 0x66 - - // PUSH8 pushes a 8-bytes value onto the stack - PUSH8 = 0x67 - - // PUSH9 pushes a 9-bytes value onto the stack - PUSH9 = 0x68 - - // PUSH10 pushes a 10-bytes value onto the stack - PUSH10 = 0x69 - - // PUSH11 pushes a 11-bytes value onto the stack - PUSH11 = 0x6A - - // PUSH12 pushes a 12-bytes value onto the stack - PUSH12 = 0x6B - - // PUSH13 pushes a 13-bytes value onto the stack - PUSH13 = 0x6C - - // PUSH14 pushes a 14-bytes value onto the stack - PUSH14 = 0x6D - - // PUSH15 pushes a 15-bytes value onto the stack - PUSH15 = 0x6E - - // PUSH16 pushes a 16-bytes value onto the stack - PUSH16 = 0x6F - - // PUSH17 pushes a 17-bytes value onto the stack - PUSH17 = 0x70 - - // PUSH18 pushes a 18-bytes value onto the stack - PUSH18 = 0x71 - - // PUSH19 pushes a 19-bytes value onto the stack - PUSH19 = 0x72 - - // PUSH20 pushes a 20-bytes value onto the stack - PUSH20 = 0x73 - - // PUSH21 pushes a 21-bytes value onto the stack - PUSH21 = 0x74 - - // PUSH22 pushes a 22-bytes value onto the stack - PUSH22 = 0x75 - - // PUSH23 pushes a 23-bytes value onto the stack - PUSH23 = 0x76 - - // PUSH24 pushes a 24-bytes value onto the stack - PUSH24 = 0x77 - - // PUSH25 pushes a 25-bytes value onto the stack - PUSH25 = 0x78 - - // PUSH26 pushes a 26-bytes value onto the stack - PUSH26 = 0x79 - - // PUSH27 pushes a 27-bytes value onto the stack - PUSH27 = 0x7A - - // PUSH28 pushes a 28-bytes value onto the stack - PUSH28 = 0x7B - - // PUSH29 pushes a 29-bytes value onto the stack - PUSH29 = 0x7C - - // PUSH30 pushes a 30-bytes value onto the stack - PUSH30 = 0x7D - - // PUSH31 pushes a 31-bytes value onto the stack - PUSH31 = 0x7E - - // PUSH32 pushes a 32-byte value onto the stack - PUSH32 = 0x7F - - // DUP1 clones the last value on the stack - DUP1 = 0x80 - - // DUP2 clones the 2nd last value on the stack - DUP2 = 0x81 - - // DUP3 clones the 3rd last value on the stack - DUP3 = 0x82 - - // DUP4 clones the 4th last value on the stack - DUP4 = 0x83 - - // DUP5 clones the 5th last value on the stack - DUP5 = 0x84 - - // DUP6 clones the 6th last value on the stack - DUP6 = 0x85 - - // DUP7 clones the 7th last value on the stack - DUP7 = 0x86 - - // DUP8 clones the 8th last value on the stack - DUP8 = 0x87 - - // DUP9 clones the 9th last value on the stack - DUP9 = 0x88 - - // DUP10 clones the 10th last value on the stack - DUP10 = 0x89 - - // DUP11 clones the 11th last value on the stack - DUP11 = 0x8A - - // DUP12 clones the 12th last value on the stack - DUP12 = 0x8B - - // DUP13 clones the 13th last value on the stack - DUP13 = 0x8C - - // DUP14 clones the 14th last value on the stack - DUP14 = 0x8D - - // DUP15 clones the 15th last value on the stack - DUP15 = 0x8E - - // DUP16 clones the 16th last value on the stack - DUP16 = 0x8F - - // SWAP1 swaps the last two values on the stack - SWAP1 = 0x90 - - // SWAP2 swaps the top of the stack with the 3rd last element - SWAP2 = 0x91 - - // SWAP3 swaps the top of the stack with the 4th last element - SWAP3 = 0x92 - - // SWAP4 swaps the top of the stack with the 5th last element - SWAP4 = 0x93 - - // SWAP5 swaps the top of the stack with the 6th last element - SWAP5 = 0x94 - - // SWAP6 swaps the top of the stack with the 7th last element - SWAP6 = 0x95 - - // SWAP7 swaps the top of the stack with the 8th last element - SWAP7 = 0x96 - - // SWAP8 swaps the top of the stack with the 9th last element - SWAP8 = 0x97 - - // SWAP9 swaps the top of the stack with the 10th last element - SWAP9 = 0x98 - - // SWAP10 swaps the top of the stack with the 11th last element - SWAP10 = 0x99 - - // SWAP11 swaps the top of the stack with the 12th last element - SWAP11 = 0x9A - - // SWAP12 swaps the top of the stack with the 13th last element - SWAP12 = 0x9B - - // SWAP13 swaps the top of the stack with the 14th last element - SWAP13 = 0x9C - - // SWAP14 swaps the top of the stack with the 15th last element - SWAP14 = 0x9D - - // SWAP15 swaps the top of the stack with the 16th last element - SWAP15 = 0x9E - - // SWAP16 swaps the top of the stack with the 17th last element - SWAP16 = 0x9F - - // LOG0 fires an event without topics - LOG0 = 0xA0 - - // LOG1 fires an event with one topic - LOG1 = 0xA1 +// IsPush specifies if an opcode is a PUSH opcode. +func (op OpCode) IsPush() bool { + return PUSH1 <= op && op <= PUSH32 +} - // LOG2 fires an event with two topics - LOG2 = 0xA2 +// 0x0 range - arithmetic ops. +const ( + STOP OpCode = 0x0 + ADD OpCode = 0x1 + MUL OpCode = 0x2 + SUB OpCode = 0x3 + DIV OpCode = 0x4 + SDIV OpCode = 0x5 + MOD OpCode = 0x6 + SMOD OpCode = 0x7 + ADDMOD OpCode = 0x8 + MULMOD OpCode = 0x9 + EXP OpCode = 0xa + SIGNEXTEND OpCode = 0xb +) - // LOG3 fires an event with three topics - LOG3 = 0xA3 +// 0x10 range - comparison ops. +const ( + LT OpCode = 0x10 + GT OpCode = 0x11 + SLT OpCode = 0x12 + SGT OpCode = 0x13 + EQ OpCode = 0x14 + ISZERO OpCode = 0x15 + AND OpCode = 0x16 + OR OpCode = 0x17 + XOR OpCode = 0x18 + NOT OpCode = 0x19 + BYTE OpCode = 0x1a + SHL OpCode = 0x1b + SHR OpCode = 0x1c + SAR OpCode = 0x1d +) - // LOG4 fires an event with four topics - LOG4 = 0xA4 +// 0x20 range - crypto. +const ( + KECCAK256 OpCode = 0x20 +) - // CREATE creates a child contract - CREATE = 0xF0 +// 0x30 range - closure state. +const ( + ADDRESS OpCode = 0x30 + BALANCE OpCode = 0x31 + ORIGIN OpCode = 0x32 + CALLER OpCode = 0x33 + CALLVALUE OpCode = 0x34 + CALLDATALOAD OpCode = 0x35 + CALLDATASIZE OpCode = 0x36 + CALLDATACOPY OpCode = 0x37 + CODESIZE OpCode = 0x38 + CODECOPY OpCode = 0x39 + GASPRICE OpCode = 0x3a + EXTCODESIZE OpCode = 0x3b + EXTCODECOPY OpCode = 0x3c + RETURNDATASIZE OpCode = 0x3d + RETURNDATACOPY OpCode = 0x3e + EXTCODEHASH OpCode = 0x3f +) - // CALL calls a method in another contract - CALL = 0xF1 +// 0x40 range - block operations. +const ( + BLOCKHASH OpCode = 0x40 + COINBASE OpCode = 0x41 + TIMESTAMP OpCode = 0x42 + NUMBER OpCode = 0x43 + DIFFICULTY OpCode = 0x44 + RANDOM OpCode = 0x44 // Same as DIFFICULTY + PREVRANDAO OpCode = 0x44 // Same as DIFFICULTY + GASLIMIT OpCode = 0x45 + CHAINID OpCode = 0x46 + SELFBALANCE OpCode = 0x47 + BASEFEE OpCode = 0x48 +) - // CALLCODE calls a method in another contract - CALLCODE = 0xF2 +// 0x50 range - 'storage' and execution. +const ( + POP OpCode = 0x50 + MLOAD OpCode = 0x51 + MSTORE OpCode = 0x52 + MSTORE8 OpCode = 0x53 + SLOAD OpCode = 0x54 + SSTORE OpCode = 0x55 + JUMP OpCode = 0x56 + JUMPI OpCode = 0x57 + PC OpCode = 0x58 + MSIZE OpCode = 0x59 + GAS OpCode = 0x5a + JUMPDEST OpCode = 0x5b + PUSH0 OpCode = 0x5f +) - // RETURN returns from this contract call - RETURN = 0xF3 +// 0x60 range - pushes. +const ( + PUSH1 OpCode = 0x60 + iota + PUSH2 + PUSH3 + PUSH4 + PUSH5 + PUSH6 + PUSH7 + PUSH8 + PUSH9 + PUSH10 + PUSH11 + PUSH12 + PUSH13 + PUSH14 + PUSH15 + PUSH16 + PUSH17 + PUSH18 + PUSH19 + PUSH20 + PUSH21 + PUSH22 + PUSH23 + PUSH24 + PUSH25 + PUSH26 + PUSH27 + PUSH28 + PUSH29 + PUSH30 + PUSH31 + PUSH32 +) - // DELEGATECALL calls a method in another contract using the storage of the current contract - DELEGATECALL = 0xF4 +// 0x80 range - dups. +const ( + DUP1 = 0x80 + iota + DUP2 + DUP3 + DUP4 + DUP5 + DUP6 + DUP7 + DUP8 + DUP9 + DUP10 + DUP11 + DUP12 + DUP13 + DUP14 + DUP15 + DUP16 +) - // CREATE2 creates a child contract with a salt - CREATE2 = 0xF5 +// 0x90 range - swaps. +const ( + SWAP1 = 0x90 + iota + SWAP2 + SWAP3 + SWAP4 + SWAP5 + SWAP6 + SWAP7 + SWAP8 + SWAP9 + SWAP10 + SWAP11 + SWAP12 + SWAP13 + SWAP14 + SWAP15 + SWAP16 +) - // STATICCALL calls a method in another contract - STATICCALL = 0xFA +// 0xa0 range - logging ops. +const ( + LOG0 OpCode = 0xa0 + iota + LOG1 + LOG2 + LOG3 + LOG4 +) - // REVERT reverts with return data - REVERT = 0xFD +// 0xf0 range - closures. +const ( + CREATE OpCode = 0xf0 + CALL OpCode = 0xf1 + CALLCODE OpCode = 0xf2 + RETURN OpCode = 0xf3 + DELEGATECALL OpCode = 0xf4 + CREATE2 OpCode = 0xf5 + + STATICCALL OpCode = 0xfa + REVERT OpCode = 0xfd + INVALID OpCode = 0xfe + SELFDESTRUCT OpCode = 0xff +) - // SELFDESTRUCT destroys the contract and sends all funds to addr - SELFDESTRUCT = 0xFF +// 0xb0 range. +const ( + TLOAD OpCode = 0xb3 + TSTORE OpCode = 0xb4 ) +// Since the opcodes aren't all in order we can't use a regular slice. var opCodeToString = map[OpCode]string{ - STOP: "STOP", - ADD: "ADD", - MUL: "MUL", - SUB: "SUB", - DIV: "DIV", - SDIV: "SDIV", - MOD: "MOD", - SMOD: "SMOD", - EXP: "EXP", - NOT: "NOT", - LT: "LT", - GT: "GT", - SLT: "SLT", - SGT: "SGT", - EQ: "EQ", - ISZERO: "ISZERO", - SIGNEXTEND: "SIGNEXTEND", - AND: "AND", - OR: "OR", - XOR: "XOR", - BYTE: "BYTE", - SHL: "SHL", - SHR: "SHR", - SAR: "SAR", - ADDMOD: "ADDMOD", - MULMOD: "MULMOD", - SHA3: "SHA3", + // 0x0 range - arithmetic ops. + STOP: "STOP", + ADD: "ADD", + MUL: "MUL", + SUB: "SUB", + DIV: "DIV", + SDIV: "SDIV", + MOD: "MOD", + SMOD: "SMOD", + EXP: "EXP", + NOT: "NOT", + LT: "LT", + GT: "GT", + SLT: "SLT", + SGT: "SGT", + EQ: "EQ", + ISZERO: "ISZERO", + SIGNEXTEND: "SIGNEXTEND", + + // 0x10 range - bit ops. + AND: "AND", + OR: "OR", + XOR: "XOR", + BYTE: "BYTE", + SHL: "SHL", + SHR: "SHR", + SAR: "SAR", + ADDMOD: "ADDMOD", + MULMOD: "MULMOD", + + // 0x20 range - crypto. + KECCAK256: "KECCAK256", + + // 0x30 range - closure state. ADDRESS: "ADDRESS", BALANCE: "BALANCE", ORIGIN: "ORIGIN", @@ -476,106 +277,284 @@ var opCodeToString = map[OpCode]string{ RETURNDATASIZE: "RETURNDATASIZE", RETURNDATACOPY: "RETURNDATACOPY", EXTCODEHASH: "EXTCODEHASH", - BLOCKHASH: "BLOCKHASH", - COINBASE: "COINBASE", - TIMESTAMP: "TIMESTAMP", - NUMBER: "NUMBER", - DIFFICULTY: "DIFFICULTY", - GASLIMIT: "GASLIMIT", - POP: "POP", - MLOAD: "MLOAD", - MSTORE: "MSTORE", - MSTORE8: "MSTORE8", - SLOAD: "SLOAD", - SSTORE: "SSTORE", - JUMP: "JUMP", - JUMPI: "JUMPI", - PC: "PC", - MSIZE: "MSIZE", - GAS: "GAS", - JUMPDEST: "JUMPDEST", - PUSH1: "PUSH1", - PUSH2: "PUSH2", - PUSH3: "PUSH3", - PUSH4: "PUSH4", - PUSH5: "PUSH5", - PUSH6: "PUSH6", - PUSH7: "PUSH7", - PUSH8: "PUSH8", - PUSH9: "PUSH9", - PUSH10: "PUSH10", - PUSH11: "PUSH11", - PUSH12: "PUSH12", - PUSH13: "PUSH13", - PUSH14: "PUSH14", - PUSH15: "PUSH15", - PUSH16: "PUSH16", - PUSH17: "PUSH17", - PUSH18: "PUSH18", - PUSH19: "PUSH19", - PUSH20: "PUSH20", - PUSH21: "PUSH21", - PUSH22: "PUSH22", - PUSH23: "PUSH23", - PUSH24: "PUSH24", - PUSH25: "PUSH25", - PUSH26: "PUSH26", - PUSH27: "PUSH27", - PUSH28: "PUSH28", - PUSH29: "PUSH29", - PUSH30: "PUSH30", - PUSH31: "PUSH31", - PUSH32: "PUSH32", - DUP1: "DUP1", - DUP2: "DUP2", - DUP3: "DUP3", - DUP4: "DUP4", - DUP5: "DUP5", - DUP6: "DUP6", - DUP7: "DUP7", - DUP8: "DUP8", - DUP9: "DUP9", - DUP10: "DUP10", - DUP11: "DUP11", - DUP12: "DUP12", - DUP13: "DUP13", - DUP14: "DUP14", - DUP15: "DUP15", - DUP16: "DUP16", - SWAP1: "SWAP1", - SWAP2: "SWAP2", - SWAP3: "SWAP3", - SWAP4: "SWAP4", - SWAP5: "SWAP5", - SWAP6: "SWAP6", - SWAP7: "SWAP7", - SWAP8: "SWAP8", - SWAP9: "SWAP9", - SWAP10: "SWAP10", - SWAP11: "SWAP11", - SWAP12: "SWAP12", - SWAP13: "SWAP13", - SWAP14: "SWAP14", - SWAP15: "SWAP15", - SWAP16: "SWAP16", - LOG0: "LOG0", - LOG1: "LOG1", - LOG2: "LOG2", - LOG3: "LOG3", - LOG4: "LOG4", - CREATE: "CREATE", - CALL: "CALL", - RETURN: "RETURN", - CALLCODE: "CALLCODE", - DELEGATECALL: "DELEGATECALL", - CREATE2: "CREATE2", - STATICCALL: "STATICCALL", - REVERT: "REVERT", - SELFDESTRUCT: "SELFDESTRUCT", - CHAINID: "CHAINID", - SELFBALANCE: "SELFBALANCE", + + // 0x40 range - block operations. + BLOCKHASH: "BLOCKHASH", + COINBASE: "COINBASE", + TIMESTAMP: "TIMESTAMP", + NUMBER: "NUMBER", + DIFFICULTY: "DIFFICULTY", // TODO (MariusVanDerWijden) rename to PREVRANDAO post merge + GASLIMIT: "GASLIMIT", + CHAINID: "CHAINID", + SELFBALANCE: "SELFBALANCE", + BASEFEE: "BASEFEE", + + // 0x50 range - 'storage' and execution. + POP: "POP", + //DUP: "DUP", + //SWAP: "SWAP", + MLOAD: "MLOAD", + MSTORE: "MSTORE", + MSTORE8: "MSTORE8", + SLOAD: "SLOAD", + SSTORE: "SSTORE", + JUMP: "JUMP", + JUMPI: "JUMPI", + PC: "PC", + MSIZE: "MSIZE", + GAS: "GAS", + JUMPDEST: "JUMPDEST", + PUSH0: "PUSH0", + + // 0x60 range - push. + PUSH1: "PUSH1", + PUSH2: "PUSH2", + PUSH3: "PUSH3", + PUSH4: "PUSH4", + PUSH5: "PUSH5", + PUSH6: "PUSH6", + PUSH7: "PUSH7", + PUSH8: "PUSH8", + PUSH9: "PUSH9", + PUSH10: "PUSH10", + PUSH11: "PUSH11", + PUSH12: "PUSH12", + PUSH13: "PUSH13", + PUSH14: "PUSH14", + PUSH15: "PUSH15", + PUSH16: "PUSH16", + PUSH17: "PUSH17", + PUSH18: "PUSH18", + PUSH19: "PUSH19", + PUSH20: "PUSH20", + PUSH21: "PUSH21", + PUSH22: "PUSH22", + PUSH23: "PUSH23", + PUSH24: "PUSH24", + PUSH25: "PUSH25", + PUSH26: "PUSH26", + PUSH27: "PUSH27", + PUSH28: "PUSH28", + PUSH29: "PUSH29", + PUSH30: "PUSH30", + PUSH31: "PUSH31", + PUSH32: "PUSH32", + + DUP1: "DUP1", + DUP2: "DUP2", + DUP3: "DUP3", + DUP4: "DUP4", + DUP5: "DUP5", + DUP6: "DUP6", + DUP7: "DUP7", + DUP8: "DUP8", + DUP9: "DUP9", + DUP10: "DUP10", + DUP11: "DUP11", + DUP12: "DUP12", + DUP13: "DUP13", + DUP14: "DUP14", + DUP15: "DUP15", + DUP16: "DUP16", + + SWAP1: "SWAP1", + SWAP2: "SWAP2", + SWAP3: "SWAP3", + SWAP4: "SWAP4", + SWAP5: "SWAP5", + SWAP6: "SWAP6", + SWAP7: "SWAP7", + SWAP8: "SWAP8", + SWAP9: "SWAP9", + SWAP10: "SWAP10", + SWAP11: "SWAP11", + SWAP12: "SWAP12", + SWAP13: "SWAP13", + SWAP14: "SWAP14", + SWAP15: "SWAP15", + SWAP16: "SWAP16", + LOG0: "LOG0", + LOG1: "LOG1", + LOG2: "LOG2", + LOG3: "LOG3", + LOG4: "LOG4", + + // 0xb0 range. + TLOAD: "TLOAD", + TSTORE: "TSTORE", + + // 0xf0 range. + CREATE: "CREATE", + CALL: "CALL", + RETURN: "RETURN", + CALLCODE: "CALLCODE", + DELEGATECALL: "DELEGATECALL", + CREATE2: "CREATE2", + STATICCALL: "STATICCALL", + REVERT: "REVERT", + INVALID: "INVALID", + SELFDESTRUCT: "SELFDESTRUCT", } func (op OpCode) String() string { - return opCodeToString[op] + str := opCodeToString[op] + if len(str) == 0 { + return fmt.Sprintf("opcode %#x not defined", int(op)) + } + + return str +} + +var stringToOp = map[string]OpCode{ + "STOP": STOP, + "ADD": ADD, + "MUL": MUL, + "SUB": SUB, + "DIV": DIV, + "SDIV": SDIV, + "MOD": MOD, + "SMOD": SMOD, + "EXP": EXP, + "NOT": NOT, + "LT": LT, + "GT": GT, + "SLT": SLT, + "SGT": SGT, + "EQ": EQ, + "ISZERO": ISZERO, + "SIGNEXTEND": SIGNEXTEND, + "AND": AND, + "OR": OR, + "XOR": XOR, + "BYTE": BYTE, + "SHL": SHL, + "SHR": SHR, + "SAR": SAR, + "ADDMOD": ADDMOD, + "MULMOD": MULMOD, + "KECCAK256": KECCAK256, + "ADDRESS": ADDRESS, + "BALANCE": BALANCE, + "ORIGIN": ORIGIN, + "CALLER": CALLER, + "CALLVALUE": CALLVALUE, + "CALLDATALOAD": CALLDATALOAD, + "CALLDATASIZE": CALLDATASIZE, + "CALLDATACOPY": CALLDATACOPY, + "CHAINID": CHAINID, + "BASEFEE": BASEFEE, + "DELEGATECALL": DELEGATECALL, + "STATICCALL": STATICCALL, + "CODESIZE": CODESIZE, + "CODECOPY": CODECOPY, + "GASPRICE": GASPRICE, + "EXTCODESIZE": EXTCODESIZE, + "EXTCODECOPY": EXTCODECOPY, + "RETURNDATASIZE": RETURNDATASIZE, + "RETURNDATACOPY": RETURNDATACOPY, + "EXTCODEHASH": EXTCODEHASH, + "BLOCKHASH": BLOCKHASH, + "COINBASE": COINBASE, + "TIMESTAMP": TIMESTAMP, + "NUMBER": NUMBER, + "DIFFICULTY": DIFFICULTY, + "GASLIMIT": GASLIMIT, + "SELFBALANCE": SELFBALANCE, + "POP": POP, + "MLOAD": MLOAD, + "MSTORE": MSTORE, + "MSTORE8": MSTORE8, + "SLOAD": SLOAD, + "SSTORE": SSTORE, + "JUMP": JUMP, + "JUMPI": JUMPI, + "PC": PC, + "MSIZE": MSIZE, + "GAS": GAS, + "JUMPDEST": JUMPDEST, + "PUSH0": PUSH0, + "TLOAD": TLOAD, + "TSTORE": TSTORE, + "PUSH1": PUSH1, + "PUSH2": PUSH2, + "PUSH3": PUSH3, + "PUSH4": PUSH4, + "PUSH5": PUSH5, + "PUSH6": PUSH6, + "PUSH7": PUSH7, + "PUSH8": PUSH8, + "PUSH9": PUSH9, + "PUSH10": PUSH10, + "PUSH11": PUSH11, + "PUSH12": PUSH12, + "PUSH13": PUSH13, + "PUSH14": PUSH14, + "PUSH15": PUSH15, + "PUSH16": PUSH16, + "PUSH17": PUSH17, + "PUSH18": PUSH18, + "PUSH19": PUSH19, + "PUSH20": PUSH20, + "PUSH21": PUSH21, + "PUSH22": PUSH22, + "PUSH23": PUSH23, + "PUSH24": PUSH24, + "PUSH25": PUSH25, + "PUSH26": PUSH26, + "PUSH27": PUSH27, + "PUSH28": PUSH28, + "PUSH29": PUSH29, + "PUSH30": PUSH30, + "PUSH31": PUSH31, + "PUSH32": PUSH32, + "DUP1": DUP1, + "DUP2": DUP2, + "DUP3": DUP3, + "DUP4": DUP4, + "DUP5": DUP5, + "DUP6": DUP6, + "DUP7": DUP7, + "DUP8": DUP8, + "DUP9": DUP9, + "DUP10": DUP10, + "DUP11": DUP11, + "DUP12": DUP12, + "DUP13": DUP13, + "DUP14": DUP14, + "DUP15": DUP15, + "DUP16": DUP16, + "SWAP1": SWAP1, + "SWAP2": SWAP2, + "SWAP3": SWAP3, + "SWAP4": SWAP4, + "SWAP5": SWAP5, + "SWAP6": SWAP6, + "SWAP7": SWAP7, + "SWAP8": SWAP8, + "SWAP9": SWAP9, + "SWAP10": SWAP10, + "SWAP11": SWAP11, + "SWAP12": SWAP12, + "SWAP13": SWAP13, + "SWAP14": SWAP14, + "SWAP15": SWAP15, + "SWAP16": SWAP16, + "LOG0": LOG0, + "LOG1": LOG1, + "LOG2": LOG2, + "LOG3": LOG3, + "LOG4": LOG4, + "CREATE": CREATE, + "CREATE2": CREATE2, + "CALL": CALL, + "RETURN": RETURN, + "CALLCODE": CALLCODE, + "REVERT": REVERT, + "INVALID": INVALID, + "SELFDESTRUCT": SELFDESTRUCT, +} + +// StringToOp finds the opcode whose name is stored in `str`. +func StringToOp(str string) OpCode { + return stringToOp[str] } diff --git a/state/runtime/fakevm/operations_acl.go b/state/runtime/fakevm/operations_acl.go new file mode 100644 index 0000000000..09ca31d3b6 --- /dev/null +++ b/state/runtime/fakevm/operations_acl.go @@ -0,0 +1,244 @@ +// Copyright 2020 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 fakevm + +import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/params" +) + +func makeGasSStoreFunc(clearingRefund uint64) gasFunc { + return func(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // If we fail the minimum gas availability invariant, fail (0) + if contract.Gas <= params.SstoreSentryGasEIP2200 { + return 0, errors.New("not enough gas for reentrancy sentry") + } + // Gas sentry honoured, do the actual gas calculation based on the stored value + var ( + y, x = stack.Back(1), stack.peek() + slot = common.Hash(x.Bytes32()) + current = evm.StateDB.GetState(contract.Address(), slot) + cost = uint64(0) + ) + // Check slot presence in the access list + if addrPresent, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent { + cost = params.ColdSloadCostEIP2929 + // If the caller cannot afford the cost, this change will be rolled back + evm.StateDB.AddSlotToAccessList(contract.Address(), slot) + if !addrPresent { + // Once we're done with YOLOv2 and schedule this for mainnet, might + // be good to remove this panic here, which is just really a + // canary to have during testing + panic("impossible case: address was not present in access list during sstore op") + } + } + value := common.Hash(y.Bytes32()) + + if current == value { // noop (1) + // EIP 2200 original clause: + // return params.SloadGasEIP2200, nil + return cost + params.WarmStorageReadCostEIP2929, nil // SLOAD_GAS + } + original := evm.StateDB.GetCommittedState(contract.Address(), x.Bytes32()) + if original == current { + if original == (common.Hash{}) { // create slot (2.1.1) + return cost + params.SstoreSetGasEIP2200, nil + } + if value == (common.Hash{}) { // delete slot (2.1.2b) + evm.StateDB.AddRefund(clearingRefund) + } + // EIP-2200 original clause: + // return params.SstoreResetGasEIP2200, nil // write existing slot (2.1.2) + return cost + (params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929), nil // write existing slot (2.1.2) + } + if original != (common.Hash{}) { + if current == (common.Hash{}) { // recreate slot (2.2.1.1) + evm.StateDB.SubRefund(clearingRefund) + } else if value == (common.Hash{}) { // delete slot (2.2.1.2) + evm.StateDB.AddRefund(clearingRefund) + } + } + if original == value { + if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1) + // EIP 2200 Original clause: + //evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.SloadGasEIP2200) + evm.StateDB.AddRefund(params.SstoreSetGasEIP2200 - params.WarmStorageReadCostEIP2929) + } else { // reset to original existing slot (2.2.2.2) + // EIP 2200 Original clause: + // evm.StateDB.AddRefund(params.SstoreResetGasEIP2200 - params.SloadGasEIP2200) + // - SSTORE_RESET_GAS redefined as (5000 - COLD_SLOAD_COST) + // - SLOAD_GAS redefined as WARM_STORAGE_READ_COST + // Final: (5000 - COLD_SLOAD_COST) - WARM_STORAGE_READ_COST + evm.StateDB.AddRefund((params.SstoreResetGasEIP2200 - params.ColdSloadCostEIP2929) - params.WarmStorageReadCostEIP2929) + } + } + // EIP-2200 original clause: + //return params.SloadGasEIP2200, nil // dirty update (2.2) + return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2) + } +} + +// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929 +// For SLOAD, if the (address, storage_key) pair (where address is the address of the contract +// whose storage is being read) is not yet in accessed_storage_keys, +// charge 2100 gas and add the pair to accessed_storage_keys. +// If the pair is already in accessed_storage_keys, charge 100 gas. +func gasSLoadEIP2929(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + loc := stack.peek() + slot := common.Hash(loc.Bytes32()) + // Check slot presence in the access list + if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent { + // If the caller cannot afford the cost, this change will be rolled back + // If he does afford it, we can skip checking the same thing later on, during execution + evm.StateDB.AddSlotToAccessList(contract.Address(), slot) + return params.ColdSloadCostEIP2929, nil + } + return params.WarmStorageReadCostEIP2929, nil +} + +// gasExtCodeCopyEIP2929 implements extcodecopy according to EIP-2929 +// EIP spec: +// > If the target is not in accessed_addresses, +// > charge COLD_ACCOUNT_ACCESS_COST gas, and add the address to accessed_addresses. +// > Otherwise, charge WARM_STORAGE_READ_COST gas. +func gasExtCodeCopyEIP2929(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + // memory expansion first (dynamic part of pre-2929 implementation) + gas, err := gasExtCodeCopy(evm, contract, stack, mem, memorySize) + if err != nil { + return 0, err + } + addr := common.Address(stack.peek().Bytes20()) + // Check slot presence in the access list + if !evm.StateDB.AddressInAccessList(addr) { + evm.StateDB.AddAddressToAccessList(addr) + var overflow bool + // We charge (cold-warm), since 'warm' is already charged as constantGas + if gas, overflow = math.SafeAdd(gas, params.ColdAccountAccessCostEIP2929-params.WarmStorageReadCostEIP2929); overflow { + return 0, ErrGasUintOverflow + } + return gas, nil + } + return gas, nil +} + +// gasEip2929AccountCheck checks whether the first stack item (as address) is present in the access list. +// If it is, this method returns '0', otherwise 'cold-warm' gas, presuming that the opcode using it +// is also using 'warm' as constant factor. +// This method is used by: +// - extcodehash, +// - extcodesize, +// - (ext) balance +func gasEip2929AccountCheck(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + addr := common.Address(stack.peek().Bytes20()) + // Check slot presence in the access list + if !evm.StateDB.AddressInAccessList(addr) { + // If the caller cannot afford the cost, this change will be rolled back + evm.StateDB.AddAddressToAccessList(addr) + // The warm storage read cost is already charged as constantGas + return params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929, nil + } + return 0, nil +} + +func makeCallVariantGasCallEIP2929(oldCalculator gasFunc) gasFunc { + return func(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + addr := common.Address(stack.Back(1).Bytes20()) + // Check slot presence in the access list + warmAccess := evm.StateDB.AddressInAccessList(addr) + // The WarmStorageReadCostEIP2929 (100) is already deducted in the form of a constant cost, so + // the cost to charge for cold access, if any, is Cold - Warm + coldCost := params.ColdAccountAccessCostEIP2929 - params.WarmStorageReadCostEIP2929 + if !warmAccess { + evm.StateDB.AddAddressToAccessList(addr) + // Charge the remaining difference here already, to correctly calculate available + // gas for call + if !contract.UseGas(coldCost) { + return 0, ErrOutOfGas + } + } + // Now call the old calculator, which takes into account + // - create new account + // - transfer value + // - memory expansion + // - 63/64ths rule + gas, err := oldCalculator(evm, contract, stack, mem, memorySize) + if warmAccess || err != nil { + return gas, err + } + // In case of a cold access, we temporarily add the cold charge back, and also + // add it to the returned gas. By adding it to the return, it will be charged + // outside of this function, as part of the dynamic gas, and that will make it + // also become correctly reported to tracers. + contract.Gas += coldCost + return gas + coldCost, nil + } +} + +var ( + gasCallEIP2929 = makeCallVariantGasCallEIP2929(gasCall) + gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall) + gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall) + gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode) + gasSelfdestructEIP2929 = makeSelfdestructGasFn(true) + // gasSelfdestructEIP3529 implements the changes in EIP-2539 (no refunds) + gasSelfdestructEIP3529 = makeSelfdestructGasFn(false) + + // gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929 + // + // When calling SSTORE, check if the (address, storage_key) pair is in accessed_storage_keys. + // If it is not, charge an additional COLD_SLOAD_COST gas, and add the pair to accessed_storage_keys. + // Additionally, modify the parameters defined in EIP 2200 as follows: + // + // Parameter Old value New value + // SLOAD_GAS 800 = WARM_STORAGE_READ_COST + // SSTORE_RESET_GAS 5000 5000 - COLD_SLOAD_COST + // + //The other parameters defined in EIP 2200 are unchanged. + // see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified + gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200) + + // gasSStoreEIP2539 implements gas cost for SSTORE according to EIP-2539 + // Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800) + gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529) +) + +// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-2539 +func makeSelfdestructGasFn(refundsEnabled bool) gasFunc { + gasFunc := func(evm *FakeEVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + var ( + gas uint64 + address = common.Address(stack.peek().Bytes20()) + ) + if !evm.StateDB.AddressInAccessList(address) { + // If the caller cannot afford the cost, this change will be rolled back + evm.StateDB.AddAddressToAccessList(address) + gas = params.ColdAccountAccessCostEIP2929 + } + // if empty and transfers value + if evm.StateDB.Empty(address) && evm.StateDB.GetBalance(contract.Address()).Sign() != 0 { + gas += params.CreateBySelfdestructGas + } + if refundsEnabled && !evm.StateDB.HasSuicided(contract.Address()) { + evm.StateDB.AddRefund(params.SelfdestructRefundGas) + } + return gas, nil + } + return gasFunc +} diff --git a/state/runtime/fakevm/stack.go b/state/runtime/fakevm/stack.go index f778f610d0..6c9e105206 100644 --- a/state/runtime/fakevm/stack.go +++ b/state/runtime/fakevm/stack.go @@ -17,18 +17,14 @@ package fakevm import ( - "fmt" "sync" "github.com/holiman/uint256" ) -// InitialStackSize represents the initial stack size. -const InitialStackSize int = 16 - var stackPool = sync.Pool{ New: func() interface{} { - return &Stack{data: make([]uint256.Int, 0, InitialStackSize)} + return &Stack{data: make([]uint256.Int, 0, 16)} }, } @@ -39,40 +35,48 @@ type Stack struct { data []uint256.Int } -// Newstack gets a stack from the pool. -func Newstack() *Stack { +func NewStack() *Stack { return stackPool.Get().(*Stack) } +func returnStack(s *Stack) { + s.data = s.data[:0] + stackPool.Put(s) +} + // Data returns the underlying uint256.Int array. func (st *Stack) Data() []uint256.Int { return st.data } -// Push adds an item to the data. func (st *Stack) Push(d *uint256.Int) { // NOTE push limit (1024) is checked in baseCheck st.data = append(st.data, *d) } +func (st *Stack) pop() (ret uint256.Int) { + ret = st.data[len(st.data)-1] + st.data = st.data[:len(st.data)-1] + return +} + func (st *Stack) len() int { return len(st.data) } +func (st *Stack) swap(n int) { + st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n] +} + +func (st *Stack) dup(n int) { + st.Push(&st.data[st.len()-n]) +} + +func (st *Stack) peek() *uint256.Int { + return &st.data[st.len()-1] +} + // Back returns the n'th item in stack func (st *Stack) Back(n int) *uint256.Int { return &st.data[st.len()-n-1] } - -// Print dumps the content of the stack -func (st *Stack) Print() { - fmt.Println("### stack ###") - if len(st.data) > 0 { - for i, val := range st.data { - fmt.Printf("%-3d %s\n", i, val.String()) - } - } else { - fmt.Println("-- empty --") - } - fmt.Println("#############") -} diff --git a/state/runtime/fakevm/stack_table.go b/state/runtime/fakevm/stack_table.go new file mode 100644 index 0000000000..b5bf72a42a --- /dev/null +++ b/state/runtime/fakevm/stack_table.go @@ -0,0 +1,42 @@ +// Copyright 2017 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 fakevm + +import ( + "github.com/ethereum/go-ethereum/params" +) + +func minSwapStack(n int) int { + return minStack(n, n) +} +func maxSwapStack(n int) int { + return maxStack(n, n) +} + +func minDupStack(n int) int { + return minStack(n, n+1) +} +func maxDupStack(n int) int { + return maxStack(n, n+1) +} + +func maxStack(pop, push int) int { + return int(params.StackLimit) + pop - push +} +func minStack(pops, push int) int { + return pops +} diff --git a/state/runtime/instrumentation/executortrace.go b/state/runtime/instrumentation/executortrace.go index 237ba044ed..8a45bbd30a 100644 --- a/state/runtime/instrumentation/executortrace.go +++ b/state/runtime/instrumentation/executortrace.go @@ -36,8 +36,8 @@ type Step struct { Contract Contract `json:"contract"` GasCost string `json:"gasCost"` Stack []string `json:"stack"` - Memory []string `json:"memory"` - ReturnData string `json:"returnData"` + Memory []byte `json:"memory"` + ReturnData []byte `json:"returnData"` } // Contract represents a contract in the trace. diff --git a/state/runtime/instrumentation/intrumentation_test.go b/state/runtime/instrumentation/intrumentation_test.go index dfdecec462..d5ea1056fd 100644 --- a/state/runtime/instrumentation/intrumentation_test.go +++ b/state/runtime/instrumentation/intrumentation_test.go @@ -4,7 +4,7 @@ package instrumentation_test import ( "context" "encoding/json" - "io/ioutil" + "io" "os" "testing" @@ -74,7 +74,7 @@ func TestSCTxs(t *testing.T) { require.NoError(t, err) defer tracerFile.Close() - byteCode, err := ioutil.ReadAll(tracerFile) + byteCode, err := io.ReadAll(tracerFile) require.NoError(t, err) err = json.Unmarshal(byteCode, &tracer) @@ -88,7 +88,7 @@ func TestSCTxs(t *testing.T) { // log.Debug(string(j)) file, _ := json.MarshalIndent(result.ExecutorTrace, "", " ") - err = ioutil.WriteFile("trace.json", file, 0644) + err = os.WriteFile("trace.json", file, 0644) require.NoError(t, err) log.Debug(string(result.ExecutorTraceResult)) diff --git a/state/runtime/instrumentation/js/goja.go b/state/runtime/instrumentation/js/goja.go index 196e703f82..6e418eaf12 100644 --- a/state/runtime/instrumentation/js/goja.go +++ b/state/runtime/instrumentation/js/goja.go @@ -1,3 +1,19 @@ +// Copyright 2022 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 js import ( @@ -5,19 +21,20 @@ import ( "errors" "fmt" "math/big" - "time" - "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" jsassets "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/js/internal/tracers" "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" "github.com/dop251/goja" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" ) +const ( + memoryPadLimit = 1024 * 1024 +) + var assetTracers = make(map[string]string) // init retrieves the JavaScript transaction tracers included in go-ethereum. @@ -27,7 +44,16 @@ func init() { if err != nil { panic(err) } - tracers.RegisterLookup(true, NewJsTracer) + type ctorFn = func(*tracers.Context, json.RawMessage) (tracers.Tracer, error) + lookup := func(code string) ctorFn { + return func(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + return NewJsTracer(code, ctx, cfg) + } + } + for name, code := range assetTracers { + tracers.DefaultDirectory.Register(name, lookup(code), true) + } + tracers.DefaultDirectory.RegisterJSEval(NewJsTracer) } // bigIntProgram is compiled once and the exported function mostly invoked to convert @@ -40,11 +66,7 @@ type fromBufFn = func(vm *goja.Runtime, buf goja.Value, allowString bool) ([]byt func toBuf(vm *goja.Runtime, bufType goja.Value, val []byte) (goja.Value, error) { // bufType is usually Uint8Array. This is equivalent to `new Uint8Array(val)` in JS. - res, err := vm.New(bufType, vm.ToValue(val)) - if err != nil { - return nil, err - } - return vm.ToValue(res), nil + return vm.New(bufType, vm.ToValue(vm.NewArrayBuffer(val))) } func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString bool) ([]byte, error) { @@ -55,6 +77,7 @@ func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString b break } return common.FromHex(obj.String()), nil + case "Array": var b []byte if err := vm.ExportTo(buf, &b); err != nil { @@ -66,15 +89,14 @@ func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString b if !obj.Get("constructor").SameAs(bufType) { break } - var b []byte - if err := vm.ExportTo(buf, &b); err != nil { - return nil, err - } + b := obj.Get("buffer").Export().(goja.ArrayBuffer).Bytes() return b, nil } return nil, fmt.Errorf("invalid buffer type") } +// jsTracer is an implementation of the Tracer interface which evaluates +// JS functions on the relevant EVM hooks. It uses Goja as its JS engine. type jsTracer struct { vm *goja.Runtime env *fakevm.FakeEVM @@ -108,11 +130,14 @@ type jsTracer struct { frameResultValue goja.Value } -// NewJsTracer is the JS tracer constructor. -func NewJsTracer(code string, ctx *tracers.Context) (tracers.Tracer, error) { - if c, ok := assetTracers[code]; ok { - code = c - } +// NewJsTracer instantiates a new JS tracer instance. code is a +// Javascript snippet which evaluates to an expression returning +// an object with certain methods: +// +// The methods `result` and `fault` are required to be present. +// The methods `step`, `enter`, and `exit` are optional, but note that +// `enter` and `exit` always go together. +func NewJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { vm := goja.New() // By default field names are exported to JS as is, i.e. capitalized. vm.SetFieldNameMapper(goja.UncapFieldNameMapper()) @@ -131,10 +156,7 @@ func NewJsTracer(code string, ctx *tracers.Context) (tracers.Tracer, error) { } } - err := t.setTypeConverters() - if err != nil { - return nil, err - } + t.setTypeConverters() t.setBuiltinFunctions() ret, err := vm.RunString("(" + code + ")") if err != nil { @@ -164,6 +186,17 @@ func NewJsTracer(code string, ctx *tracers.Context) (tracers.Tracer, error) { t.exit = exit t.result = result t.fault = fault + + // Pass in config + if setup, ok := goja.AssertFunction(obj.Get("setup")); ok { + cfgStr := "{}" + if cfg != nil { + cfgStr = string(cfg) + } + if _, err := setup(obj, vm.ToValue(cfgStr)); err != nil { + return nil, err + } + } // Setup objects carrying data to JS. These are created once and re-used. t.log = &steplog{ vm: vm, @@ -188,7 +221,9 @@ func (t *jsTracer) CaptureTxStart(gasLimit uint64) { // CaptureTxEnd implements the Tracer interface and is invoked at the end of // transaction processing. -func (t *jsTracer) CaptureTxEnd(restGas uint64) {} +func (t *jsTracer) CaptureTxEnd(restGas uint64) { + t.ctx["gasUsed"] = t.vm.ToValue(t.gasLimit - restGas) +} // CaptureStart implements the Tracer interface to initialize the tracing operation. func (t *jsTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { @@ -213,13 +248,12 @@ func (t *jsTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to com t.ctx["value"] = valueBig t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil) - t.activePrecompiles = vm.ActivePrecompiles(rules) - t.ctx["intrinsicGas"] = t.vm.ToValue(t.gasLimit - gas) + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = fakevm.ActivePrecompiles(rules) } // CaptureState implements the Tracer interface to trace a single step of VM execution. -func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { +func (t *jsTracer) CaptureState(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { if !t.traceStep { return } @@ -232,10 +266,11 @@ func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope log.memory.memory = scope.Memory log.stack.stack = scope.Stack log.contract.contract = scope.Contract - log.pc = uint(pc) - log.gas = uint(gas) - log.cost = uint(cost) - log.depth = uint(depth) + log.pc = pc + log.gas = gas + log.cost = cost + log.refund = t.env.StateDB.GetRefund() + log.depth = depth log.err = err if _, err := t.step(t.obj, t.logValue, t.dbValue); err != nil { t.onError("step", err) @@ -243,7 +278,7 @@ func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope } // CaptureFault implements the Tracer interface to trace an execution fault -func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, depth int, err error) { +func (t *jsTracer) CaptureFault(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, depth int, err error) { if t.err != nil { return } @@ -255,17 +290,15 @@ func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope } // CaptureEnd is called after the call finishes to finalize the tracing. -func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, duration time.Duration, err error) { +func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { t.ctx["output"] = t.vm.ToValue(output) - t.ctx["time"] = t.vm.ToValue(duration.String()) - t.ctx["gasUsed"] = t.vm.ToValue(gasUsed) if err != nil { t.ctx["error"] = t.vm.ToValue(err.Error()) } } // CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). -func (t *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +func (t *jsTracer) CaptureEnter(typ fakevm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { if !t.traceFrame { return } @@ -342,7 +375,7 @@ func wrapError(context string, err error) error { func (t *jsTracer) setBuiltinFunctions() { vm := t.vm // TODO: load console from goja-nodejs - err := vm.Set("toHex", func(v goja.Value) string { + vm.Set("toHex", func(v goja.Value) string { b, err := t.fromBuf(vm, v, false) if err != nil { vm.Interrupt(err) @@ -350,10 +383,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return hexutil.Encode(b) }) - if err != nil { - log.Error(err) - } - err = vm.Set("toWord", func(v goja.Value) goja.Value { + vm.Set("toWord", func(v goja.Value) goja.Value { // TODO: add test with []byte len < 32 or > 32 b, err := t.fromBuf(vm, v, true) if err != nil { @@ -368,10 +398,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return res }) - if err != nil { - log.Error(err) - } - err = vm.Set("toAddress", func(v goja.Value) goja.Value { + vm.Set("toAddress", func(v goja.Value) goja.Value { a, err := t.fromBuf(vm, v, true) if err != nil { vm.Interrupt(err) @@ -385,10 +412,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return res }) - if err != nil { - log.Error(err) - } - err = vm.Set("toContract", func(from goja.Value, nonce uint) goja.Value { + vm.Set("toContract", func(from goja.Value, nonce uint) goja.Value { a, err := t.fromBuf(vm, from, true) if err != nil { vm.Interrupt(err) @@ -403,10 +427,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return res }) - if err != nil { - log.Error(err) - } - err = vm.Set("toContract2", func(from goja.Value, salt string, initcode goja.Value) goja.Value { + vm.Set("toContract2", func(from goja.Value, salt string, initcode goja.Value) goja.Value { a, err := t.fromBuf(vm, from, true) if err != nil { vm.Interrupt(err) @@ -428,10 +449,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return res }) - if err != nil { - log.Error(err) - } - err = vm.Set("isPrecompiled", func(v goja.Value) bool { + vm.Set("isPrecompiled", func(v goja.Value) bool { a, err := t.fromBuf(vm, v, true) if err != nil { vm.Interrupt(err) @@ -445,10 +463,7 @@ func (t *jsTracer) setBuiltinFunctions() { } return false }) - if err != nil { - log.Error(err) - } - err = vm.Set("slice", func(slice goja.Value, start, end int) goja.Value { + vm.Set("slice", func(slice goja.Value, start, end int) goja.Value { b, err := t.fromBuf(vm, slice, false) if err != nil { vm.Interrupt(err) @@ -465,9 +480,6 @@ func (t *jsTracer) setBuiltinFunctions() { } return res }) - if err != nil { - log.Error(err) - } } // setTypeConverters sets up utilities for converting Go types into those @@ -506,7 +518,7 @@ func (t *jsTracer) setTypeConverters() error { type opObj struct { vm *goja.Runtime - op vm.OpCode + op fakevm.OpCode } func (o *opObj) ToNumber() int { @@ -523,18 +535,9 @@ func (o *opObj) IsPush() bool { func (o *opObj) setupObject() *goja.Object { obj := o.vm.NewObject() - err := obj.Set("toNumber", o.vm.ToValue(o.ToNumber)) - if err != nil { - log.Error(err) - } - err = obj.Set("toString", o.vm.ToValue(o.ToString)) - if err != nil { - log.Error(err) - } - err = obj.Set("isPush", o.vm.ToValue(o.IsPush)) - if err != nil { - log.Error(err) - } + obj.Set("toNumber", o.vm.ToValue(o.ToNumber)) + obj.Set("toString", o.vm.ToValue(o.ToString)) + obj.Set("isPush", o.vm.ToValue(o.IsPush)) return obj } @@ -565,12 +568,17 @@ func (mo *memoryObj) slice(begin, end int64) ([]byte, error) { return []byte{}, nil } if end < begin || begin < 0 { - return nil, fmt.Errorf("Tracer accessed out of bound memory: offset %d, end %d", begin, end) + return nil, fmt.Errorf("tracer accessed out of bound memory: offset %d, end %d", begin, end) } - if mo.memory.Len() < int(end) { - return nil, fmt.Errorf("Tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), begin, end-begin) + mlen := mo.memory.Len() + if end-int64(mlen) > memoryPadLimit { + return nil, fmt.Errorf("tracer reached limit for padding memory slice: end %d, memorySize %d", end, mlen) } - return mo.memory.GetCopy(begin, end-begin), nil + slice := make([]byte, end-begin) + end = min(end, int64(mo.memory.Len())) + ptr := mo.memory.GetPtr(begin, end-begin) + copy(slice[:], ptr[:]) + return slice, nil } func (mo *memoryObj) GetUint(addr int64) goja.Value { @@ -590,29 +598,20 @@ func (mo *memoryObj) GetUint(addr int64) goja.Value { // getUint returns the 32 bytes at the specified address interpreted as a uint. func (mo *memoryObj) getUint(addr int64) (*big.Int, error) { if mo.memory.Len() < int(addr)+32 || addr < 0 { - return nil, fmt.Errorf("Tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), addr, fakevm.MemoryItemSize) + return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), addr, 32) } - return new(big.Int).SetBytes(mo.memory.GetPtr(addr, int64(fakevm.MemoryItemSize))), nil + return new(big.Int).SetBytes(mo.memory.GetPtr(addr, 32)), nil } func (mo *memoryObj) Length() int { return mo.memory.Len() } -func (mo *memoryObj) setupObject() *goja.Object { - o := mo.vm.NewObject() - err := o.Set("slice", mo.vm.ToValue(mo.Slice)) - if err != nil { - log.Error(err) - } - err = o.Set("getUint", mo.vm.ToValue(mo.GetUint)) - if err != nil { - log.Error(err) - } - err = o.Set("length", mo.vm.ToValue(mo.Length)) - if err != nil { - log.Error(err) - } +func (m *memoryObj) setupObject() *goja.Object { + o := m.vm.NewObject() + o.Set("slice", m.vm.ToValue(m.Slice)) + o.Set("getUint", m.vm.ToValue(m.GetUint)) + o.Set("length", m.vm.ToValue(m.Length)) return o } @@ -639,7 +638,7 @@ func (s *stackObj) Peek(idx int) goja.Value { // peek returns the nth-from-the-top element of the stack. func (s *stackObj) peek(idx int) (*big.Int, error) { if len(s.stack.Data()) <= idx || idx < 0 { - return nil, fmt.Errorf("Tracer accessed out of bound stack: size %d, index %d", len(s.stack.Data()), idx) + return nil, fmt.Errorf("tracer accessed out of bound stack: size %d, index %d", len(s.stack.Data()), idx) } return s.stack.Back(idx).ToBig(), nil } @@ -650,14 +649,8 @@ func (s *stackObj) Length() int { func (s *stackObj) setupObject() *goja.Object { o := s.vm.NewObject() - err := o.Set("peek", s.vm.ToValue(s.Peek)) - if err != nil { - log.Error(err) - } - err = o.Set("length", s.vm.ToValue(s.Length)) - if err != nil { - log.Error(err) - } + o.Set("peek", s.vm.ToValue(s.Peek)) + o.Set("length", s.vm.ToValue(s.Length)) return o } @@ -745,31 +738,16 @@ func (do *dbObj) Exists(addrSlice goja.Value) bool { func (do *dbObj) setupObject() *goja.Object { o := do.vm.NewObject() - err := o.Set("getBalance", do.vm.ToValue(do.GetBalance)) - if err != nil { - log.Error(err) - } - err = o.Set("getNonce", do.vm.ToValue(do.GetNonce)) - if err != nil { - log.Error(err) - } - err = o.Set("getCode", do.vm.ToValue(do.GetCode)) - if err != nil { - log.Error(err) - } - err = o.Set("getState", do.vm.ToValue(do.GetState)) - if err != nil { - log.Error(err) - } - err = o.Set("exists", do.vm.ToValue(do.Exists)) - if err != nil { - log.Error(err) - } + o.Set("getBalance", do.vm.ToValue(do.GetBalance)) + o.Set("getNonce", do.vm.ToValue(do.GetNonce)) + o.Set("getCode", do.vm.ToValue(do.GetCode)) + o.Set("getState", do.vm.ToValue(do.GetState)) + o.Set("exists", do.vm.ToValue(do.Exists)) return o } type contractObj struct { - contract *vm.Contract + contract *fakevm.Contract vm *goja.Runtime toBig toBigFn toBuf toBufFn @@ -806,7 +784,7 @@ func (co *contractObj) GetValue() goja.Value { } func (co *contractObj) GetInput() goja.Value { - input := co.contract.Input + input := common.CopyBytes(co.contract.Input) res, err := co.toBuf(co.vm, input) if err != nil { co.vm.Interrupt(err) @@ -815,24 +793,12 @@ func (co *contractObj) GetInput() goja.Value { return res } -func (co *contractObj) setupObject() *goja.Object { - o := co.vm.NewObject() - err := o.Set("getCaller", co.vm.ToValue(co.GetCaller)) - if err != nil { - log.Error(err) - } - err = o.Set("getAddress", co.vm.ToValue(co.GetAddress)) - if err != nil { - log.Error(err) - } - err = o.Set("getValue", co.vm.ToValue(co.GetValue)) - if err != nil { - log.Error(err) - } - err = o.Set("getInput", co.vm.ToValue(co.GetInput)) - if err != nil { - log.Error(err) - } +func (c *contractObj) setupObject() *goja.Object { + o := c.vm.NewObject() + o.Set("getCaller", c.vm.ToValue(c.GetCaller)) + o.Set("getAddress", c.vm.ToValue(c.GetAddress)) + o.Set("getValue", c.vm.ToValue(c.GetValue)) + o.Set("getInput", c.vm.ToValue(c.GetInput)) return o } @@ -901,30 +867,12 @@ func (f *callframe) GetValue() goja.Value { func (f *callframe) setupObject() *goja.Object { o := f.vm.NewObject() - err := o.Set("getType", f.vm.ToValue(f.GetType)) - if err != nil { - log.Error(err) - } - err = o.Set("getFrom", f.vm.ToValue(f.GetFrom)) - if err != nil { - log.Error(err) - } - err = o.Set("getTo", f.vm.ToValue(f.GetTo)) - if err != nil { - log.Error(err) - } - err = o.Set("getInput", f.vm.ToValue(f.GetInput)) - if err != nil { - log.Error(err) - } - err = o.Set("getGas", f.vm.ToValue(f.GetGas)) - if err != nil { - log.Error(err) - } - err = o.Set("getValue", f.vm.ToValue(f.GetValue)) - if err != nil { - log.Error(err) - } + o.Set("getType", f.vm.ToValue(f.GetType)) + o.Set("getFrom", f.vm.ToValue(f.GetFrom)) + o.Set("getTo", f.vm.ToValue(f.GetTo)) + o.Set("getInput", f.vm.ToValue(f.GetInput)) + o.Set("getGas", f.vm.ToValue(f.GetGas)) + o.Set("getValue", f.vm.ToValue(f.GetValue)) return o } @@ -959,18 +907,9 @@ func (r *callframeResult) GetError() goja.Value { func (r *callframeResult) setupObject() *goja.Object { o := r.vm.NewObject() - err := o.Set("getGasUsed", r.vm.ToValue(r.GetGasUsed)) - if err != nil { - log.Error(err) - } - err = o.Set("getOutput", r.vm.ToValue(r.GetOutput)) - if err != nil { - log.Error(err) - } - err = o.Set("getError", r.vm.ToValue(r.GetError)) - if err != nil { - log.Error(err) - } + o.Set("getGasUsed", r.vm.ToValue(r.GetGasUsed)) + o.Set("getOutput", r.vm.ToValue(r.GetOutput)) + o.Set("getError", r.vm.ToValue(r.GetError)) return o } @@ -982,33 +921,19 @@ type steplog struct { stack *stackObj contract *contractObj - pc uint - gas uint - cost uint - depth uint - refund uint + pc uint64 + gas uint64 + cost uint64 + depth int + refund uint64 err error } -func (l *steplog) GetPC() uint { - return l.pc -} - -func (l *steplog) GetGas() uint { - return l.gas -} - -func (l *steplog) GetCost() uint { - return l.cost -} - -func (l *steplog) GetDepth() uint { - return l.depth -} - -func (l *steplog) GetRefund() uint { - return l.refund -} +func (l *steplog) GetPC() uint64 { return l.pc } +func (l *steplog) GetGas() uint64 { return l.gas } +func (l *steplog) GetCost() uint64 { return l.cost } +func (l *steplog) GetDepth() int { return l.depth } +func (l *steplog) GetRefund() uint64 { return l.refund } func (l *steplog) GetError() goja.Value { if l.err != nil { @@ -1020,46 +945,23 @@ func (l *steplog) GetError() goja.Value { func (l *steplog) setupObject() *goja.Object { o := l.vm.NewObject() // Setup basic fields. - err := o.Set("getPC", l.vm.ToValue(l.GetPC)) - if err != nil { - log.Error(err) - } - err = o.Set("getGas", l.vm.ToValue(l.GetGas)) - if err != nil { - log.Error(err) - } - err = o.Set("getCost", l.vm.ToValue(l.GetCost)) - if err != nil { - log.Error(err) - } - err = o.Set("getDepth", l.vm.ToValue(l.GetDepth)) - if err != nil { - log.Error(err) - } - err = o.Set("getRefund", l.vm.ToValue(l.GetRefund)) - if err != nil { - log.Error(err) - } - err = o.Set("getError", l.vm.ToValue(l.GetError)) - if err != nil { - log.Error(err) - } + o.Set("getPC", l.vm.ToValue(l.GetPC)) + o.Set("getGas", l.vm.ToValue(l.GetGas)) + o.Set("getCost", l.vm.ToValue(l.GetCost)) + o.Set("getDepth", l.vm.ToValue(l.GetDepth)) + o.Set("getRefund", l.vm.ToValue(l.GetRefund)) + o.Set("getError", l.vm.ToValue(l.GetError)) // Setup nested objects. - err = o.Set("op", l.op.setupObject()) - if err != nil { - log.Error(err) - } - err = o.Set("stack", l.stack.setupObject()) - if err != nil { - log.Error(err) - } - err = o.Set("memory", l.memory.setupObject()) - if err != nil { - log.Error(err) - } - err = o.Set("contract", l.contract.setupObject()) - if err != nil { - log.Error(err) - } + o.Set("op", l.op.setupObject()) + o.Set("stack", l.stack.setupObject()) + o.Set("memory", l.memory.setupObject()) + o.Set("contract", l.contract.setupObject()) return o } + +func min(a, b int64) int64 { + if a < b { + return a + } + return b +} diff --git a/state/runtime/instrumentation/tracers/native/4byte.go b/state/runtime/instrumentation/tracers/native/4byte.go new file mode 100644 index 0000000000..524f26f7fc --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/4byte.go @@ -0,0 +1,132 @@ +// Copyright 2021 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 native + +import ( + "encoding/json" + "math/big" + "strconv" + "sync/atomic" + + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/ethereum/go-ethereum/common" +) + +func init() { + tracers.DefaultDirectory.Register("4byteTracer", NewFourByteTracer, false) +} + +// fourByteTracer searches for 4byte-identifiers, and collects them for post-processing. +// It collects the methods identifiers along with the size of the supplied data, so +// a reversed signature can be matched against the size of the data. +// +// Example: +// +// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"}) +// { +// 0x27dc297e-128: 1, +// 0x38cc4831-0: 2, +// 0x524f3889-96: 1, +// 0xadf59f99-288: 1, +// 0xc281d19e-0: 1 +// } +type fourByteTracer struct { + noopTracer + ids map[string]int // ids aggregates the 4byte ids found + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + activePrecompiles []common.Address // Updated on CaptureStart based on given rules +} + +// NewFourByteTracer returns a native go tracer which collects +// 4 byte-identifiers of a tx, and implements vm.EVMLogger. +func NewFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + t := &fourByteTracer{ + ids: make(map[string]int), + } + return t, nil +} + +// isPrecompiled returns whether the addr is a precompile. Logic borrowed from newJsTracer in eth/tracers/js/tracer.go +func (t *fourByteTracer) isPrecompiled(addr common.Address) bool { + for _, p := range t.activePrecompiles { + if p == addr { + return true + } + } + return false +} + +// store saves the given identifier and datasize. +func (t *fourByteTracer) store(id []byte, size int) { + key := bytesToHex(id) + "-" + strconv.Itoa(size) + t.ids[key] += 1 +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *fourByteTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = fakevm.ActivePrecompiles(rules) + + // Save the outer calldata also + if len(input) >= 4 { + t.store(input[0:4], len(input)-4) + } +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *fourByteTracer) CaptureEnter(op fakevm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + return + } + if len(input) < 4 { + return + } + // primarily we want to avoid CREATE/CREATE2/SELFDESTRUCT + if op != fakevm.DELEGATECALL && op != fakevm.STATICCALL && + op != fakevm.CALL && op != fakevm.CALLCODE { + return + } + // Skip any pre-compile invocations, those are just fancy opcodes + if t.isPrecompiled(to) { + return + } + t.store(input[0:4], len(input)-4) +} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *fourByteTracer) GetResult() (json.RawMessage, error) { + res, err := json.Marshal(t.ids) + if err != nil { + return nil, err + } + return res, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *fourByteTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +func bytesToHex(s []byte) string { + return "0x" + common.Bytes2Hex(s) +} diff --git a/state/runtime/instrumentation/tracers/native/call.go b/state/runtime/instrumentation/tracers/native/call.go new file mode 100644 index 0000000000..a4975ed114 --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/call.go @@ -0,0 +1,270 @@ +// Copyright 2021 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 native + +import ( + "encoding/json" + "errors" + "math/big" + "sync/atomic" + + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go + +func init() { + tracers.DefaultDirectory.Register("callTracer", NewCallTracer, false) +} + +type callLog struct { + Address common.Address `json:"address"` + Topics []common.Hash `json:"topics"` + Data hexutil.Bytes `json:"data"` +} + +type callFrame struct { + Type fakevm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas uint64 `json:"gas"` + GasUsed uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input []byte `json:"input" rlp:"optional"` + Output []byte `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Calls []callFrame `json:"calls,omitempty" rlp:"optional"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + // Placed at end on purpose. The RLP will be decoded to 0 instead of + // nil if there are non-empty elements after in the struct. + Value *big.Int `json:"value,omitempty" rlp:"optional"` +} + +func (f callFrame) TypeString() string { + return f.Type.String() +} + +func (f callFrame) failed() bool { + return len(f.Error) > 0 +} + +func (f *callFrame) processOutput(output []byte, err error) { + output = common.CopyBytes(output) + if err == nil { + f.Output = output + return + } + f.Error = err.Error() + if f.Type == fakevm.CREATE || f.Type == fakevm.CREATE2 { + f.To = nil + } + if !errors.Is(err, fakevm.ErrExecutionReverted) || len(output) == 0 { + return + } + f.Output = output + if len(output) < 4 { + return + } + if unpacked, err := abi.UnpackRevert(output); err == nil { + f.RevertReason = unpacked + } +} + +type callFrameMarshaling struct { + TypeString string `json:"type"` + Gas hexutil.Uint64 + GasUsed hexutil.Uint64 + Value *hexutil.Big + Input hexutil.Bytes + Output hexutil.Bytes +} + +type callTracer struct { + noopTracer + callstack []callFrame + config callTracerConfig + gasLimit uint64 + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption +} + +type callTracerConfig struct { + OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls + WithLog bool `json:"withLog"` // If true, call tracer will collect event logs +} + +// NewCallTracer returns a native go tracer which tracks +// call frames of a tx, and implements fakevm.EVMLogger. +func NewCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config callTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + // First callframe contains tx context info + // and is populated on start and end. + return &callTracer{callstack: make([]callFrame, 1), config: config}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *callTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + toCopy := to + t.callstack[0] = callFrame{ + Type: fakevm.CALL, + From: from, + To: &toCopy, + Input: common.CopyBytes(input), + Gas: gas, + Value: value, + } + if create { + t.callstack[0].Type = fakevm.CREATE + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { + t.callstack[0].processOutput(output, err) +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *callTracer) CaptureState(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { + // Only logs need to be captured via opcode processing + if !t.config.WithLog { + return + } + // Avoid processing nested calls when only caring about top call + if t.config.OnlyTopCall && depth > 0 { + return + } + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + return + } + switch op { + case fakevm.LOG0, fakevm.LOG1, fakevm.LOG2, fakevm.LOG3, fakevm.LOG4: + size := int(op - fakevm.LOG0) + + stack := scope.Stack + stackData := stack.Data() + + // Don't modify the stack + mStart := stackData[len(stackData)-1] + mSize := stackData[len(stackData)-2] + topics := make([]common.Hash, size) + for i := 0; i < size; i++ { + topic := stackData[len(stackData)-2-(i+1)] + topics[i] = common.Hash(topic.Bytes32()) + } + + data := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64())) + log := callLog{Address: scope.Contract.Address(), Topics: topics, Data: hexutil.Bytes(data)} + t.callstack[len(t.callstack)-1].Logs = append(t.callstack[len(t.callstack)-1].Logs, log) + } +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *callTracer) CaptureEnter(typ fakevm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if t.config.OnlyTopCall { + return + } + // Skip if tracing was interrupted + if atomic.LoadUint32(&t.interrupt) > 0 { + return + } + + toCopy := to + call := callFrame{ + Type: typ, + From: from, + To: &toCopy, + Input: common.CopyBytes(input), + Gas: gas, + Value: value, + } + t.callstack = append(t.callstack, call) +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + if t.config.OnlyTopCall { + return + } + size := len(t.callstack) + if size <= 1 { + return + } + // pop call + call := t.callstack[size-1] + t.callstack = t.callstack[:size-1] + size -= 1 + + call.GasUsed = gasUsed + call.processOutput(output, err) + t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call) +} + +func (t *callTracer) CaptureTxStart(gasLimit uint64) { + t.gasLimit = gasLimit +} + +func (t *callTracer) CaptureTxEnd(restGas uint64) { + t.callstack[0].GasUsed = t.gasLimit - restGas + if t.config.WithLog { + // Logs are not emitted when the call fails + clearFailedLogs(&t.callstack[0], false) + } +} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *callTracer) GetResult() (json.RawMessage, error) { + if len(t.callstack) != 1 { + return nil, errors.New("incorrect number of top-level calls") + } + + res, err := json.Marshal(t.callstack[0]) + if err != nil { + return nil, err + } + return json.RawMessage(res), t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *callTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +// clearFailedLogs clears the logs of a callframe and all its children +// in case of execution failure. +func clearFailedLogs(cf *callFrame, parentFailed bool) { + failed := cf.failed() || parentFailed + // Clear own logs + if failed { + cf.Logs = nil + } + for i := range cf.Calls { + clearFailedLogs(&cf.Calls[i], failed) + } +} diff --git a/state/runtime/instrumentation/tracers/native/call_flat.go b/state/runtime/instrumentation/tracers/native/call_flat.go new file mode 100644 index 0000000000..c91077f9de --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/call_flat.go @@ -0,0 +1,379 @@ +// Copyright 2022 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 native + +import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +//go:generate go run github.com/fjl/gencodec -type flatCallAction -field-override flatCallActionMarshaling -out gen_flatcallaction_json.go +//go:generate go run github.com/fjl/gencodec -type flatCallResult -field-override flatCallResultMarshaling -out gen_flatcallresult_json.go + +func init() { + tracers.DefaultDirectory.Register("flatCallTracer", newFlatCallTracer, false) +} + +var parityErrorMapping = map[string]string{ + "contract creation code storage out of gas": "Out of gas", + "out of gas": "Out of gas", + "gas uint64 overflow": "Out of gas", + "max code size exceeded": "Out of gas", + "invalid jump destination": "Bad jump destination", + "execution reverted": "Reverted", + "return data out of bounds": "Out of bounds", + "stack limit reached 1024 (1023)": "Out of stack", + "precompiled failed": "Built-in failed", + "invalid input length": "Built-in failed", +} + +var parityErrorMappingStartingWith = map[string]string{ + "invalid opcode:": "Bad instruction", + "stack underflow": "Stack underflow", +} + +// flatCallFrame is a standalone callframe. +type flatCallFrame struct { + Action flatCallAction `json:"action"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber uint64 `json:"blockNumber"` + Error string `json:"error,omitempty"` + Result *flatCallResult `json:"result,omitempty"` + Subtraces int `json:"subtraces"` + TraceAddress []int `json:"traceAddress"` + TransactionHash *common.Hash `json:"transactionHash"` + TransactionPosition uint64 `json:"transactionPosition"` + Type string `json:"type"` +} + +type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *big.Int `json:"balance,omitempty"` + CallType string `json:"callType,omitempty"` + CreationMethod string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *uint64 `json:"gas,omitempty"` + Init *[]byte `json:"init,omitempty"` + Input *[]byte `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *big.Int `json:"value,omitempty"` +} + +type flatCallActionMarshaling struct { + Balance *hexutil.Big + Gas *hexutil.Uint64 + Init *hexutil.Bytes + Input *hexutil.Bytes + Value *hexutil.Big +} + +type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *[]byte `json:"code,omitempty"` + GasUsed *uint64 `json:"gasUsed,omitempty"` + Output *[]byte `json:"output,omitempty"` +} + +type flatCallResultMarshaling struct { + Code *hexutil.Bytes + GasUsed *hexutil.Uint64 + Output *hexutil.Bytes +} + +// flatCallTracer reports call frame information of a tx in a flat format, i.e. +// as opposed to the nested format of `callTracer`. +type flatCallTracer struct { + tracer *callTracer + config flatCallTracerConfig + ctx *tracers.Context // Holds tracer context data + reason error // Textual reason for the interruption + activePrecompiles []common.Address // Updated on CaptureStart based on given rules +} + +type flatCallTracerConfig struct { + ConvertParityErrors bool `json:"convertParityErrors"` // If true, call tracer converts errors to parity format + IncludePrecompiles bool `json:"includePrecompiles"` // If true, call tracer includes calls to precompiled contracts +} + +// newFlatCallTracer returns a new flatCallTracer. +func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config flatCallTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + + tracer, err := tracers.DefaultDirectory.New("callTracer", ctx, cfg) + if err != nil { + return nil, err + } + t, ok := tracer.(*callTracer) + if !ok { + return nil, errors.New("internal error: embedded tracer has wrong type") + } + + return &flatCallTracer{tracer: t, ctx: ctx, config: config}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *flatCallTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.tracer.CaptureStart(env, from, to, create, input, gas, value) + // Update list of precompiles based on current block + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + t.activePrecompiles = fakevm.ActivePrecompiles(rules) +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { + t.tracer.CaptureEnd(output, gasUsed, err) +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *flatCallTracer) CaptureState(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { + t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err) +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *flatCallTracer) CaptureFault(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, depth int, err error) { + t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err) +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *flatCallTracer) CaptureEnter(typ fakevm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + t.tracer.CaptureEnter(typ, from, to, input, gas, value) + + // Child calls must have a value, even if it's zero. + // Practically speaking, only STATICCALL has nil value. Set it to zero. + if t.tracer.callstack[len(t.tracer.callstack)-1].Value == nil && value == nil { + t.tracer.callstack[len(t.tracer.callstack)-1].Value = big.NewInt(0) + } +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + t.tracer.CaptureExit(output, gasUsed, err) + + // Parity traces don't include CALL/STATICCALLs to precompiles. + // By default we remove them from the callstack. + if t.config.IncludePrecompiles { + return + } + var ( + // call has been nested in parent + parent = t.tracer.callstack[len(t.tracer.callstack)-1] + call = parent.Calls[len(parent.Calls)-1] + typ = call.Type + to = call.To + ) + if typ == fakevm.CALL || typ == fakevm.STATICCALL { + if t.isPrecompiled(*to) { + t.tracer.callstack[len(t.tracer.callstack)-1].Calls = parent.Calls[:len(parent.Calls)-1] + } + } +} + +func (t *flatCallTracer) CaptureTxStart(gasLimit uint64) { + t.tracer.CaptureTxStart(gasLimit) +} + +func (t *flatCallTracer) CaptureTxEnd(restGas uint64) { + t.tracer.CaptureTxEnd(restGas) +} + +// GetResult returns an empty json object. +func (t *flatCallTracer) GetResult() (json.RawMessage, error) { + if len(t.tracer.callstack) < 1 { + return nil, errors.New("invalid number of calls") + } + + flat, err := flatFromNested(&t.tracer.callstack[0], []int{}, t.config.ConvertParityErrors, t.ctx) + if err != nil { + return nil, err + } + + res, err := json.Marshal(flat) + if err != nil { + return nil, err + } + return res, t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *flatCallTracer) Stop(err error) { + t.tracer.Stop(err) +} + +// isPrecompiled returns whether the addr is a precompile. +func (t *flatCallTracer) isPrecompiled(addr common.Address) bool { + for _, p := range t.activePrecompiles { + if p == addr { + return true + } + } + return false +} + +func flatFromNested(input *callFrame, traceAddress []int, convertErrs bool, ctx *tracers.Context) (output []flatCallFrame, err error) { + var frame *flatCallFrame + switch input.Type { + case fakevm.CREATE, fakevm.CREATE2: + frame = newFlatCreate(input) + case fakevm.SELFDESTRUCT: + frame = newFlatSuicide(input) + case fakevm.CALL, fakevm.STATICCALL, fakevm.CALLCODE, fakevm.DELEGATECALL: + frame = newFlatCall(input) + default: + return nil, fmt.Errorf("unrecognized call frame type: %s", input.Type) + } + + frame.TraceAddress = traceAddress + frame.Error = input.Error + frame.Subtraces = len(input.Calls) + fillCallFrameFromContext(frame, ctx) + if convertErrs { + convertErrorToParity(frame) + } + + // Revert output contains useful information (revert reason). + // Otherwise discard result. + if input.Error != "" && input.Error != fakevm.ErrExecutionReverted.Error() { + frame.Result = nil + } + + output = append(output, *frame) + if len(input.Calls) > 0 { + for i, childCall := range input.Calls { + childAddr := childTraceAddress(traceAddress, i) + childCallCopy := childCall + flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx) + if err != nil { + return nil, err + } + output = append(output, flat...) + } + } + + return output, nil +} + +func newFlatCreate(input *callFrame) *flatCallFrame { + var ( + actionInit = input.Input[:] + resultCode = input.Output[:] + ) + + return &flatCallFrame{ + Type: strings.ToLower(fakevm.CREATE.String()), + Action: flatCallAction{ + From: &input.From, + Gas: &input.Gas, + Value: input.Value, + Init: &actionInit, + }, + Result: &flatCallResult{ + GasUsed: &input.GasUsed, + Address: input.To, + Code: &resultCode, + }, + } +} + +func newFlatCall(input *callFrame) *flatCallFrame { + var ( + actionInput = input.Input[:] + resultOutput = input.Output[:] + ) + + return &flatCallFrame{ + Type: strings.ToLower(fakevm.CALL.String()), + Action: flatCallAction{ + From: &input.From, + To: input.To, + Gas: &input.Gas, + Value: input.Value, + CallType: strings.ToLower(input.Type.String()), + Input: &actionInput, + }, + Result: &flatCallResult{ + GasUsed: &input.GasUsed, + Output: &resultOutput, + }, + } +} + +func newFlatSuicide(input *callFrame) *flatCallFrame { + return &flatCallFrame{ + Type: "suicide", + Action: flatCallAction{ + SelfDestructed: &input.From, + Balance: input.Value, + RefundAddress: input.To, + }, + } +} + +func fillCallFrameFromContext(callFrame *flatCallFrame, ctx *tracers.Context) { + if ctx == nil { + return + } + if ctx.BlockHash != (common.Hash{}) { + callFrame.BlockHash = &ctx.BlockHash + } + if ctx.BlockNumber != nil { + callFrame.BlockNumber = ctx.BlockNumber.Uint64() + } + if ctx.TxHash != (common.Hash{}) { + callFrame.TransactionHash = &ctx.TxHash + } + callFrame.TransactionPosition = uint64(ctx.TxIndex) +} + +func convertErrorToParity(call *flatCallFrame) { + if call.Error == "" { + return + } + + if parityError, ok := parityErrorMapping[call.Error]; ok { + call.Error = parityError + } else { + for gethError, parityError := range parityErrorMappingStartingWith { + if strings.HasPrefix(call.Error, gethError) { + call.Error = parityError + } + } + } +} + +func childTraceAddress(a []int, i int) []int { + child := make([]int, 0, len(a)+1) + child = append(child, a...) + child = append(child, i) + return child +} diff --git a/state/runtime/instrumentation/tracers/native/gen_account_json.go b/state/runtime/instrumentation/tracers/native/gen_account_json.go new file mode 100644 index 0000000000..4c39cbc38c --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/gen_account_json.go @@ -0,0 +1,56 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*accountMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (a account) MarshalJSON() ([]byte, error) { + type account struct { + Balance *hexutil.Big `json:"balance,omitempty"` + Code hexutil.Bytes `json:"code,omitempty"` + Nonce uint64 `json:"nonce,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` + } + var enc account + enc.Balance = (*hexutil.Big)(a.Balance) + enc.Code = a.Code + enc.Nonce = a.Nonce + enc.Storage = a.Storage + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (a *account) UnmarshalJSON(input []byte) error { + type account struct { + Balance *hexutil.Big `json:"balance,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + Nonce *uint64 `json:"nonce,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` + } + var dec account + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Balance != nil { + a.Balance = (*big.Int)(dec.Balance) + } + if dec.Code != nil { + a.Code = *dec.Code + } + if dec.Nonce != nil { + a.Nonce = *dec.Nonce + } + if dec.Storage != nil { + a.Storage = dec.Storage + } + return nil +} diff --git a/state/runtime/instrumentation/tracers/native/gen_callframe_json.go b/state/runtime/instrumentation/tracers/native/gen_callframe_json.go new file mode 100644 index 0000000000..b17cb22dd8 --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/gen_callframe_json.go @@ -0,0 +1,107 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" +) + +var _ = (*callFrameMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (c callFrame) MarshalJSON() ([]byte, error) { + type callFrame0 struct { + Type fakevm.OpCode `json:"-"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasUsed hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input hexutil.Bytes `json:"input" rlp:"optional"` + Output hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error string `json:"error,omitempty" rlp:"optional"` + RevertReason string `json:"revertReason,omitempty"` + Calls []callFrame `json:"calls,omitempty" rlp:"optional"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + TypeString string `json:"type"` + } + var enc callFrame0 + enc.Type = c.Type + enc.From = c.From + enc.Gas = hexutil.Uint64(c.Gas) + enc.GasUsed = hexutil.Uint64(c.GasUsed) + enc.To = c.To + enc.Input = c.Input + enc.Output = c.Output + enc.Error = c.Error + enc.RevertReason = c.RevertReason + enc.Calls = c.Calls + enc.Logs = c.Logs + enc.Value = (*hexutil.Big)(c.Value) + enc.TypeString = c.TypeString() + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (c *callFrame) UnmarshalJSON(input []byte) error { + type callFrame0 struct { + Type *fakevm.OpCode `json:"-"` + From *common.Address `json:"from"` + Gas *hexutil.Uint64 `json:"gas"` + GasUsed *hexutil.Uint64 `json:"gasUsed"` + To *common.Address `json:"to,omitempty" rlp:"optional"` + Input *hexutil.Bytes `json:"input" rlp:"optional"` + Output *hexutil.Bytes `json:"output,omitempty" rlp:"optional"` + Error *string `json:"error,omitempty" rlp:"optional"` + RevertReason *string `json:"revertReason,omitempty"` + Calls []callFrame `json:"calls,omitempty" rlp:"optional"` + Logs []callLog `json:"logs,omitempty" rlp:"optional"` + Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` + } + var dec callFrame0 + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Type != nil { + c.Type = *dec.Type + } + if dec.From != nil { + c.From = *dec.From + } + if dec.Gas != nil { + c.Gas = uint64(*dec.Gas) + } + if dec.GasUsed != nil { + c.GasUsed = uint64(*dec.GasUsed) + } + if dec.To != nil { + c.To = dec.To + } + if dec.Input != nil { + c.Input = *dec.Input + } + if dec.Output != nil { + c.Output = *dec.Output + } + if dec.Error != nil { + c.Error = *dec.Error + } + if dec.RevertReason != nil { + c.RevertReason = *dec.RevertReason + } + if dec.Calls != nil { + c.Calls = dec.Calls + } + if dec.Logs != nil { + c.Logs = dec.Logs + } + if dec.Value != nil { + c.Value = (*big.Int)(dec.Value) + } + return nil +} diff --git a/state/runtime/instrumentation/tracers/native/gen_flatcallaction_json.go b/state/runtime/instrumentation/tracers/native/gen_flatcallaction_json.go new file mode 100644 index 0000000000..c075606983 --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/gen_flatcallaction_json.go @@ -0,0 +1,110 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*flatCallActionMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (f flatCallAction) MarshalJSON() ([]byte, error) { + type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *hexutil.Big `json:"balance,omitempty"` + CallType string `json:"callType,omitempty"` + CreationMethod string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *hexutil.Uint64 `json:"gas,omitempty"` + Init *hexutil.Bytes `json:"init,omitempty"` + Input *hexutil.Bytes `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *hexutil.Big `json:"value,omitempty"` + } + var enc flatCallAction + enc.Author = f.Author + enc.RewardType = f.RewardType + enc.SelfDestructed = f.SelfDestructed + enc.Balance = (*hexutil.Big)(f.Balance) + enc.CallType = f.CallType + enc.CreationMethod = f.CreationMethod + enc.From = f.From + enc.Gas = (*hexutil.Uint64)(f.Gas) + enc.Init = (*hexutil.Bytes)(f.Init) + enc.Input = (*hexutil.Bytes)(f.Input) + enc.RefundAddress = f.RefundAddress + enc.To = f.To + enc.Value = (*hexutil.Big)(f.Value) + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (f *flatCallAction) UnmarshalJSON(input []byte) error { + type flatCallAction struct { + Author *common.Address `json:"author,omitempty"` + RewardType *string `json:"rewardType,omitempty"` + SelfDestructed *common.Address `json:"address,omitempty"` + Balance *hexutil.Big `json:"balance,omitempty"` + CallType *string `json:"callType,omitempty"` + CreationMethod *string `json:"creationMethod,omitempty"` + From *common.Address `json:"from,omitempty"` + Gas *hexutil.Uint64 `json:"gas,omitempty"` + Init *hexutil.Bytes `json:"init,omitempty"` + Input *hexutil.Bytes `json:"input,omitempty"` + RefundAddress *common.Address `json:"refundAddress,omitempty"` + To *common.Address `json:"to,omitempty"` + Value *hexutil.Big `json:"value,omitempty"` + } + var dec flatCallAction + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Author != nil { + f.Author = dec.Author + } + if dec.RewardType != nil { + f.RewardType = *dec.RewardType + } + if dec.SelfDestructed != nil { + f.SelfDestructed = dec.SelfDestructed + } + if dec.Balance != nil { + f.Balance = (*big.Int)(dec.Balance) + } + if dec.CallType != nil { + f.CallType = *dec.CallType + } + if dec.CreationMethod != nil { + f.CreationMethod = *dec.CreationMethod + } + if dec.From != nil { + f.From = dec.From + } + if dec.Gas != nil { + f.Gas = (*uint64)(dec.Gas) + } + if dec.Init != nil { + f.Init = (*[]byte)(dec.Init) + } + if dec.Input != nil { + f.Input = (*[]byte)(dec.Input) + } + if dec.RefundAddress != nil { + f.RefundAddress = dec.RefundAddress + } + if dec.To != nil { + f.To = dec.To + } + if dec.Value != nil { + f.Value = (*big.Int)(dec.Value) + } + return nil +} diff --git a/state/runtime/instrumentation/tracers/native/gen_flatcallresult_json.go b/state/runtime/instrumentation/tracers/native/gen_flatcallresult_json.go new file mode 100644 index 0000000000..e9fa5e44da --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/gen_flatcallresult_json.go @@ -0,0 +1,55 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package native + +import ( + "encoding/json" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var _ = (*flatCallResultMarshaling)(nil) + +// MarshalJSON marshals as JSON. +func (f flatCallResult) MarshalJSON() ([]byte, error) { + type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` + Output *hexutil.Bytes `json:"output,omitempty"` + } + var enc flatCallResult + enc.Address = f.Address + enc.Code = (*hexutil.Bytes)(f.Code) + enc.GasUsed = (*hexutil.Uint64)(f.GasUsed) + enc.Output = (*hexutil.Bytes)(f.Output) + return json.Marshal(&enc) +} + +// UnmarshalJSON unmarshals from JSON. +func (f *flatCallResult) UnmarshalJSON(input []byte) error { + type flatCallResult struct { + Address *common.Address `json:"address,omitempty"` + Code *hexutil.Bytes `json:"code,omitempty"` + GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` + Output *hexutil.Bytes `json:"output,omitempty"` + } + var dec flatCallResult + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Address != nil { + f.Address = dec.Address + } + if dec.Code != nil { + f.Code = (*[]byte)(dec.Code) + } + if dec.GasUsed != nil { + f.GasUsed = (*uint64)(dec.GasUsed) + } + if dec.Output != nil { + f.Output = (*[]byte)(dec.Output) + } + return nil +} diff --git a/state/runtime/instrumentation/tracers/native/mux.go b/state/runtime/instrumentation/tracers/native/mux.go new file mode 100644 index 0000000000..db8ddd6438 --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/mux.go @@ -0,0 +1,138 @@ +// Copyright 2022 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 native + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" +) + +func init() { + tracers.DefaultDirectory.Register("muxTracer", newMuxTracer, false) +} + +// muxTracer is a go implementation of the Tracer interface which +// runs multiple tracers in one go. +type muxTracer struct { + names []string + tracers []tracers.Tracer +} + +// newMuxTracer returns a new mux tracer. +func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config map[string]json.RawMessage + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + objects := make([]tracers.Tracer, 0, len(config)) + names := make([]string, 0, len(config)) + for k, v := range config { + t, err := tracers.DefaultDirectory.New(k, ctx, v) + if err != nil { + return nil, err + } + objects = append(objects, t) + names = append(names, k) + } + + return &muxTracer{names: names, tracers: objects}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *muxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + for _, t := range t.tracers { + t.CaptureStart(env, from, to, create, input, gas, value) + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { + for _, t := range t.tracers { + t.CaptureEnd(output, gasUsed, err) + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *muxTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { + for _, t := range t.tracers { + t.CaptureState(pc, op, gas, cost, scope, rData, depth, err) + } +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *muxTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) { + for _, t := range t.tracers { + t.CaptureFault(pc, op, gas, cost, scope, depth, err) + } +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *muxTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + for _, t := range t.tracers { + t.CaptureEnter(typ, from, to, input, gas, value) + } +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error) { + for _, t := range t.tracers { + t.CaptureExit(output, gasUsed, err) + } +} + +func (t *muxTracer) CaptureTxStart(gasLimit uint64) { + for _, t := range t.tracers { + t.CaptureTxStart(gasLimit) + } +} + +func (t *muxTracer) CaptureTxEnd(restGas uint64) { + for _, t := range t.tracers { + t.CaptureTxEnd(restGas) + } +} + +// GetResult returns an empty json object. +func (t *muxTracer) GetResult() (json.RawMessage, error) { + resObject := make(map[string]json.RawMessage) + for i, tt := range t.tracers { + r, err := tt.GetResult() + if err != nil { + return nil, err + } + resObject[t.names[i]] = r + } + res, err := json.Marshal(resObject) + if err != nil { + return nil, err + } + return res, nil +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *muxTracer) Stop(err error) { + for _, t := range t.tracers { + t.Stop(err) + } +} diff --git a/state/runtime/instrumentation/tracers/native/noop.go b/state/runtime/instrumentation/tracers/native/noop.go new file mode 100644 index 0000000000..fc692363fb --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/noop.go @@ -0,0 +1,77 @@ +// Copyright 2021 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 native + +import ( + "encoding/json" + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/ethereum/go-ethereum/common" +) + +func init() { + tracers.DefaultDirectory.Register("noopTracer", NewNoopTracer, false) +} + +// noopTracer is a go implementation of the Tracer interface which +// performs no action. It's mostly useful for testing purposes. +type noopTracer struct{} + +// NewNoopTracer returns a new noop tracer. +func NewNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) { + return &noopTracer{}, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *noopTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *noopTracer) CaptureState(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { +} + +// CaptureFault implements the EVMLogger interface to trace an execution fault. +func (t *noopTracer) CaptureFault(pc uint64, op fakevm.OpCode, gas, cost uint64, _ *fakevm.ScopeContext, depth int, err error) { +} + +// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). +func (t *noopTracer) CaptureEnter(typ fakevm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { +} + +// CaptureExit is called when EVM exits a scope, even if the scope didn't +// execute any code. +func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) { +} + +func (*noopTracer) CaptureTxStart(gasLimit uint64) {} + +func (*noopTracer) CaptureTxEnd(restGas uint64) {} + +// GetResult returns an empty json object. +func (t *noopTracer) GetResult() (json.RawMessage, error) { + return json.RawMessage(`{}`), nil +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *noopTracer) Stop(err error) { +} diff --git a/state/runtime/instrumentation/tracers/native/prestate.go b/state/runtime/instrumentation/tracers/native/prestate.go new file mode 100644 index 0000000000..16d99a23d4 --- /dev/null +++ b/state/runtime/instrumentation/tracers/native/prestate.go @@ -0,0 +1,285 @@ +// Copyright 2022 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 native + +import ( + "bytes" + "encoding/json" + "math/big" + "sync/atomic" + + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" +) + +//go:generate go run github.com/fjl/gencodec -type account -field-override accountMarshaling -out gen_account_json.go + +func init() { + tracers.DefaultDirectory.Register("prestateTracer", NewPrestateTracer, false) +} + +type state = map[common.Address]*account + +type account struct { + Balance *big.Int `json:"balance,omitempty"` + Code []byte `json:"code,omitempty"` + Nonce uint64 `json:"nonce,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` +} + +func (a *account) exists() bool { + return a.Nonce > 0 || len(a.Code) > 0 || len(a.Storage) > 0 || (a.Balance != nil && a.Balance.Sign() != 0) +} + +type accountMarshaling struct { + Balance *hexutil.Big + Code hexutil.Bytes +} + +type prestateTracer struct { + noopTracer + env *fakevm.FakeEVM + pre state + post state + create bool + to common.Address + gasLimit uint64 // Amount of gas bought for the whole tx + config prestateTracerConfig + interrupt uint32 // Atomic flag to signal execution interruption + reason error // Textual reason for the interruption + created map[common.Address]bool + deleted map[common.Address]bool +} + +type prestateTracerConfig struct { + DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications +} + +func NewPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) { + var config prestateTracerConfig + if cfg != nil { + if err := json.Unmarshal(cfg, &config); err != nil { + return nil, err + } + } + return &prestateTracer{ + pre: state{}, + post: state{}, + config: config, + created: make(map[common.Address]bool), + deleted: make(map[common.Address]bool), + }, nil +} + +// CaptureStart implements the EVMLogger interface to initialize the tracing operation. +func (t *prestateTracer) CaptureStart(env *fakevm.FakeEVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { + t.env = env + t.create = create + t.to = to + + t.lookupAccount(from) + t.lookupAccount(to) + t.lookupAccount(env.Context.Coinbase) + + // The recipient balance includes the value transferred. + toBal := new(big.Int).Sub(t.pre[to].Balance, value) + t.pre[to].Balance = toBal + + // The sender balance is after reducing: value and gasLimit. + // We need to re-add them to get the pre-tx balance. + fromBal := new(big.Int).Set(t.pre[from].Balance) + gasPrice := env.TxContext.GasPrice + consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit)) + fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas)) + t.pre[from].Balance = fromBal + t.pre[from].Nonce-- + + if create && t.config.DiffMode { + t.created[to] = true + } +} + +// CaptureEnd is called after the call finishes to finalize the tracing. +func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { + if t.config.DiffMode { + return + } + + if t.create { + // Keep existing account prior to contract creation at that address + if s := t.pre[t.to]; s != nil && !s.exists() { + // Exclude newly created contract. + delete(t.pre, t.to) + } + } +} + +// CaptureState implements the EVMLogger interface to trace a single step of VM execution. +func (t *prestateTracer) CaptureState(pc uint64, op fakevm.OpCode, gas, cost uint64, scope *fakevm.ScopeContext, rData []byte, depth int, err error) { + stack := scope.Stack + stackData := stack.Data() + stackLen := len(stackData) + caller := scope.Contract.Address() + switch { + case stackLen >= 1 && (op == fakevm.SLOAD || op == fakevm.SSTORE): + slot := common.Hash(stackData[stackLen-1].Bytes32()) + t.lookupStorage(caller, slot) + case stackLen >= 1 && (op == fakevm.EXTCODECOPY || op == fakevm.EXTCODEHASH || op == fakevm.EXTCODESIZE || op == fakevm.BALANCE || op == fakevm.SELFDESTRUCT): + addr := common.Address(stackData[stackLen-1].Bytes20()) + t.lookupAccount(addr) + if op == fakevm.SELFDESTRUCT { + t.deleted[caller] = true + } + case stackLen >= 5 && (op == fakevm.DELEGATECALL || op == fakevm.CALL || op == fakevm.STATICCALL || op == fakevm.CALLCODE): + addr := common.Address(stackData[stackLen-2].Bytes20()) + t.lookupAccount(addr) + case op == fakevm.CREATE: + nonce := t.env.StateDB.GetNonce(caller) + addr := crypto.CreateAddress(caller, nonce) + t.lookupAccount(addr) + t.created[addr] = true + case stackLen >= 4 && op == fakevm.CREATE2: + offset := stackData[stackLen-2] + size := stackData[stackLen-3] + init := scope.Memory.GetCopy(int64(offset.Uint64()), int64(size.Uint64())) + inithash := crypto.Keccak256(init) + salt := stackData[stackLen-4] + addr := crypto.CreateAddress2(caller, salt.Bytes32(), inithash) + t.lookupAccount(addr) + t.created[addr] = true + } +} + +func (t *prestateTracer) CaptureTxStart(gasLimit uint64) { + t.gasLimit = gasLimit +} + +func (t *prestateTracer) CaptureTxEnd(restGas uint64) { + if !t.config.DiffMode { + return + } + + for addr, state := range t.pre { + // The deleted account's state is pruned from `post` but kept in `pre` + if _, ok := t.deleted[addr]; ok { + continue + } + modified := false + postAccount := &account{Storage: make(map[common.Hash]common.Hash)} + newBalance := t.env.StateDB.GetBalance(addr) + newNonce := t.env.StateDB.GetNonce(addr) + newCode := t.env.StateDB.GetCode(addr) + + if newBalance.Cmp(t.pre[addr].Balance) != 0 { + modified = true + postAccount.Balance = newBalance + } + if newNonce != t.pre[addr].Nonce { + modified = true + postAccount.Nonce = newNonce + } + if !bytes.Equal(newCode, t.pre[addr].Code) { + modified = true + postAccount.Code = newCode + } + + for key, val := range state.Storage { + // don't include the empty slot + if val == (common.Hash{}) { + delete(t.pre[addr].Storage, key) + } + + newVal := t.env.StateDB.GetState(addr, key) + if val == newVal { + // Omit unchanged slots + delete(t.pre[addr].Storage, key) + } else { + modified = true + if newVal != (common.Hash{}) { + postAccount.Storage[key] = newVal + } + } + } + + if modified { + t.post[addr] = postAccount + } else { + // if state is not modified, then no need to include into the pre state + delete(t.pre, addr) + } + } + // the new created contracts' prestate were empty, so delete them + for a := range t.created { + // the created contract maybe exists in statedb before the creating tx + if s := t.pre[a]; s != nil && !s.exists() { + delete(t.pre, a) + } + } +} + +// GetResult returns the json-encoded nested list of call traces, and any +// error arising from the encoding or forceful termination (via `Stop`). +func (t *prestateTracer) GetResult() (json.RawMessage, error) { + var res []byte + var err error + if t.config.DiffMode { + res, err = json.Marshal(struct { + Post state `json:"post"` + Pre state `json:"pre"` + }{t.post, t.pre}) + } else { + res, err = json.Marshal(t.pre) + } + if err != nil { + return nil, err + } + return json.RawMessage(res), t.reason +} + +// Stop terminates execution of the tracer at the first opportune moment. +func (t *prestateTracer) Stop(err error) { + t.reason = err + atomic.StoreUint32(&t.interrupt, 1) +} + +// lookupAccount fetches details of an account and adds it to the prestate +// if it doesn't exist there. +func (t *prestateTracer) lookupAccount(addr common.Address) { + if _, ok := t.pre[addr]; ok { + return + } + + t.pre[addr] = &account{ + Balance: t.env.StateDB.GetBalance(addr), + Nonce: t.env.StateDB.GetNonce(addr), + Code: t.env.StateDB.GetCode(addr), + Storage: make(map[common.Hash]common.Hash), + } +} + +// lookupStorage fetches the requested storage slot and adds +// it to the prestate of the given contract. It assumes `lookupAccount` +// has been performed on the contract before. +func (t *prestateTracer) lookupStorage(addr common.Address, key common.Hash) { + if _, ok := t.pre[addr].Storage[key]; ok { + return + } + t.pre[addr].Storage[key] = t.env.StateDB.GetState(addr, key) +} diff --git a/state/runtime/instrumentation/tracers/tracers.go b/state/runtime/instrumentation/tracers/tracers.go index 3523834660..ec21f91e2c 100644 --- a/state/runtime/instrumentation/tracers/tracers.go +++ b/state/runtime/instrumentation/tracers/tracers.go @@ -19,7 +19,7 @@ package tracers import ( "encoding/json" - "errors" + "math/big" "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" "github.com/ethereum/go-ethereum/common" @@ -28,9 +28,10 @@ import ( // Context contains some contextual infos for a transaction execution that is not // available from within the EVM object. type Context struct { - BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call) - TxIndex int // Index of the transaction within a block (zero if dangling tx or call) - TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) + BlockHash common.Hash // Hash of the block the tx is contained within (zero if dangling tx or call) + BlockNumber *big.Int // Number of the block the tx is contained within (zero if dangling tx or call) + TxIndex int // Index of the transaction within a block (zero if dangling tx or call) + TxHash common.Hash // Hash of the transaction being traced (zero if dangling call) } // Tracer interface extends vm.EVMLogger and additionally @@ -42,31 +43,55 @@ type Tracer interface { Stop(err error) } -type lookupFunc func(string, *Context) (Tracer, error) +type ctorFn func(*Context, json.RawMessage) (Tracer, error) +type jsCtorFn func(string, *Context, json.RawMessage) (Tracer, error) -var ( - lookups []lookupFunc -) +type elem struct { + ctor ctorFn + isJS bool +} -// RegisterLookup registers a method as a lookup for tracers, meaning that -// users can invoke a named tracer through that lookup. If 'wildcard' is true, -// then the lookup will be placed last. This is typically meant for interpreted -// engines (js) which can evaluate dynamic user-supplied code. -func RegisterLookup(wildcard bool, lookup lookupFunc) { - if wildcard { - lookups = append(lookups, lookup) - } else { - lookups = append([]lookupFunc{lookup}, lookups...) - } +// DefaultDirectory is the collection of tracers bundled by default. +var DefaultDirectory = directory{elems: make(map[string]elem)} + +// directory provides functionality to lookup a tracer by name +// and a function to instantiate it. It falls back to a JS code evaluator +// if no tracer of the given name exists. +type directory struct { + elems map[string]elem + jsEval jsCtorFn +} + +// Register registers a method as a lookup for tracers, meaning that +// users can invoke a named tracer through that lookup. +func (d *directory) Register(name string, f ctorFn, isJS bool) { + d.elems[name] = elem{ctor: f, isJS: isJS} +} + +// RegisterJSEval registers a tracer that is able to parse +// dynamic user-provided JS code. +func (d *directory) RegisterJSEval(f jsCtorFn) { + d.jsEval = f } // New returns a new instance of a tracer, by iterating through the -// registered lookups. -func New(code string, ctx *Context) (Tracer, error) { - for _, lookup := range lookups { - if tracer, err := lookup(code, ctx); err == nil { - return tracer, nil - } +// registered lookups. Name is either name of an existing tracer +// or an arbitrary JS code. +func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (Tracer, error) { + if elem, ok := d.elems[name]; ok { + return elem.ctor(ctx, cfg) + } + // Assume JS code + return d.jsEval(name, ctx, cfg) +} + +// IsJS will return true if the given tracer will evaluate +// JS code. Because code evaluation has high overhead, this +// info will be used in determining fast and slow code paths. +func (d *directory) IsJS(name string) bool { + if elem, ok := d.elems[name]; ok { + return elem.isJS } - return nil, errors.New("tracer not found") + // JS eval will execute JS code + return true } diff --git a/state/runtime/runtime.go b/state/runtime/runtime.go index ed26f40459..d7363b0917 100644 --- a/state/runtime/runtime.go +++ b/state/runtime/runtime.go @@ -15,30 +15,60 @@ var ( ErrStackOverflow = errors.New("stack overflow") // ErrStackUnderflow indicates a stack overflow has happened ErrStackUnderflow = errors.New("stack underflow") - // ErrNotEnoughFunds indicates there is not enough funds to continue the execution - ErrNotEnoughFunds = errors.New("not enough funds") - // ErrInsufficientBalance indicates there is not enough balance to continue the execution - ErrInsufficientBalance = errors.New("insufficient balance for transfer") - // ErrCodeNotFound indicates the code was not found - ErrCodeNotFound = errors.New("code not found, data is empty") // ErrMaxCodeSizeExceeded indicates the code size is beyond the maximum ErrMaxCodeSizeExceeded = errors.New("evm: max code size exceeded") // ErrContractAddressCollision there is a collision regarding contract addresses ErrContractAddressCollision = errors.New("contract address collision") - // ErrDepth indicates the maximun call depth has been passed - ErrDepth = errors.New("max call depth exceeded") // ErrExecutionReverted indicates the execution has been reverted ErrExecutionReverted = errors.New("execution reverted") - // ErrCodeStoreOutOfGas indicates there is not enough gas for the storage - ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") - // ErrOutOfCounters indicates the executor run out of counters while executing the transaction - ErrOutOfCounters = errors.New("executor run out of counters") - // ErrInvalidTransaction indicates the executor found the transaction to be invalid - ErrInvalidTransaction = errors.New("invalid transaction") - // ErrIntrinsicInvalidTransaction indicates the executor found the transaction to be invalid and this does not affected the state - ErrIntrinsicInvalidTransaction = errors.New("intrinsic invalid transaction") + // ErrOutOfCountersStep indicates there are not enough step counters to continue the execution + ErrOutOfCountersStep = errors.New("not enough step counters to continue the execution") + // ErrOutOfCountersKeccak indicates there are not enough keccak counters to continue the execution + ErrOutOfCountersKeccak = errors.New("not enough keccak counters to continue the execution") + // ErrOutOfCountersBinary indicates there are not enough binary counters to continue the execution + ErrOutOfCountersBinary = errors.New("not enough binary counters to continue the execution") + // ErrOutOfCountersMemory indicates there are not enough memory align counters to continue the execution + ErrOutOfCountersMemory = errors.New("not enough memory align counters counters to continue the execution") + // ErrOutOfCountersArith indicates there are not enough arith counters to continue the execution + ErrOutOfCountersArith = errors.New("not enough arith counters counters to continue the execution") + // ErrOutOfCountersPadding indicates there are not enough padding counters to continue the execution + ErrOutOfCountersPadding = errors.New("not enough padding counters counters to continue the execution") + // ErrOutOfCountersPoseidon indicates there are not enough poseidon counters to continue the execution + ErrOutOfCountersPoseidon = errors.New("not enough poseidon counters counters to continue the execution") + // ErrIntrinsicInvalidSignature indicates the transaction is failing at the signature intrinsic check + ErrIntrinsicInvalidSignature = errors.New("signature intrinsic error") + // ErrIntrinsicInvalidChainID indicates the transaction is failing at the chain id intrinsic check + ErrIntrinsicInvalidChainID = errors.New("chain id intrinsic error") + // ErrIntrinsicInvalidNonce indicates the transaction is failing at the nonce intrinsic check + ErrIntrinsicInvalidNonce = errors.New("nonce intrinsic error") + // ErrIntrinsicInvalidGasLimit indicates the transaction is failing at the gas limit intrinsic check + ErrIntrinsicInvalidGasLimit = errors.New("gas limit intrinsic error") + // ErrIntrinsicInvalidBalance indicates the transaction is failing at balance intrinsic check + ErrIntrinsicInvalidBalance = errors.New("balance intrinsic error") + // ErrIntrinsicInvalidBatchGasLimit indicates the batch is exceeding the batch gas limit + ErrIntrinsicInvalidBatchGasLimit = errors.New("batch gas limit intrinsic error") + // ErrIntrinsicInvalidSenderCode indicates the sender code is invalid + ErrIntrinsicInvalidSenderCode = errors.New("invalid sender code intrinsic error") // ErrBatchDataTooBig indicates the batch_l2_data is too big to be processed ErrBatchDataTooBig = errors.New("batch data too big") + // ErrInvalidJump indicates there is an invalid jump opcode + ErrInvalidJump = errors.New("invalid jump opcode") + // ErrInvalidOpCode indicates there is an invalid opcode + ErrInvalidOpCode = errors.New("invalid opcode") + // ErrInvalidStatic indicates there is an invalid static call + ErrInvalidStatic = errors.New("invalid static call") + // ErrInvalidByteCodeStartsEF indicates there is a byte code starting with 0xEF + ErrInvalidByteCodeStartsEF = errors.New("byte code starting with 0xEF") + // ErrIntrinsicInvalidTxGasOverflow indicates the transaction gasLimit*gasPrice > MAX_UINT_256 - 1 + ErrIntrinsicInvalidTxGasOverflow = errors.New("gas overflow") + // ErrUnsupportedForkId indicates that the fork id is not supported + ErrUnsupportedForkId = errors.New("unsupported fork id") + // ErrBalanceMismatch indicates that the balance mismatch in the ROM + ErrBalanceMismatch = errors.New("balance mismatch") + // ErrFea2Scalar indicates a fea2scalar error in the ROM + ErrFea2Scalar = errors.New("fea2scalar") + // ErrTos32 indicates a tos32 error in the ROM + ErrTos32 = errors.New("tos32") ) // ExecutionResult includes all output after executing given evm diff --git a/state/state.go b/state/state.go index 5b741a8a58..865a17f793 100644 --- a/state/state.go +++ b/state/state.go @@ -2,44 +2,18 @@ package state import ( "context" - "encoding/json" - "errors" - "fmt" "math/big" - "strconv" - "strings" - "time" + "sync" - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/event" "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/state/runtime" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/js" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/trie" - "github.com/holiman/uint256" "github.com/jackc/pgx/v4" ) -const ( - // Size of the memory in bytes reserved by the zkEVM - zkEVMReservedMemorySize int = 128 - two uint = 2 - three uint64 = 3 - cTrue = 1 - cFalse = 0 -) - var ( // ZeroHash is the hash 0x0000000000000000000000000000000000000000000000000000000000000000 ZeroHash = common.Hash{} @@ -47,22 +21,37 @@ var ( ZeroAddress = common.Address{} ) -// State is a implementation of the state +// State is an implementation of the state type State struct { cfg Config *PostgresStorage executorClient pb.ExecutorServiceClient tree *merkletree.StateTree + eventLog *event.EventLog + + lastL2BlockSeen types.Block + newL2BlockEvents chan NewL2BlockEvent + newL2BlockEventHandlers []NewL2BlockEventHandler } // NewState creates a new State -func NewState(cfg Config, storage *PostgresStorage, executorClient pb.ExecutorServiceClient, stateTree *merkletree.StateTree) *State { - return &State{ - cfg: cfg, - PostgresStorage: storage, - executorClient: executorClient, - tree: stateTree, +func NewState(cfg Config, storage *PostgresStorage, executorClient pb.ExecutorServiceClient, stateTree *merkletree.StateTree, eventLog *event.EventLog) *State { + var once sync.Once + once.Do(func() { + metrics.Register() + }) + + state := &State{ + cfg: cfg, + PostgresStorage: storage, + executorClient: executorClient, + tree: stateTree, + eventLog: eventLog, + newL2BlockEvents: make(chan NewL2BlockEvent), + newL2BlockEventHandlers: []NewL2BlockEventHandler{}, } + + return state } // BeginStateTransaction starts a state transaction @@ -75,33 +64,27 @@ func (s *State) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) { } // GetBalance from a given address -func (s *State) GetBalance(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) { - l2Block, err := s.GetL2BlockByNumber(ctx, blockNumber, dbTx) - if err != nil { - return nil, err +func (s *State) GetBalance(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + if s.tree == nil { + return nil, ErrStateTreeNil } - - return s.tree.GetBalance(ctx, address, l2Block.Root().Bytes()) + return s.tree.GetBalance(ctx, address, root.Bytes()) } // GetCode from a given address -func (s *State) GetCode(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) ([]byte, error) { - l2Block, err := s.GetL2BlockByNumber(ctx, blockNumber, dbTx) - if err != nil { - return nil, err +func (s *State) GetCode(ctx context.Context, address common.Address, root common.Hash) ([]byte, error) { + if s.tree == nil { + return nil, ErrStateTreeNil } - - return s.tree.GetCode(ctx, address, l2Block.Root().Bytes()) + return s.tree.GetCode(ctx, address, root.Bytes()) } // GetNonce returns the nonce of the given account at the given block number -func (s *State) GetNonce(ctx context.Context, address common.Address, blockNumber uint64, dbTx pgx.Tx) (uint64, error) { - l2Block, err := s.GetL2BlockByNumber(ctx, blockNumber, dbTx) - if err != nil { - return 0, err +func (s *State) GetNonce(ctx context.Context, address common.Address, root common.Hash) (uint64, error) { + if s.tree == nil { + return 0, ErrStateTreeNil } - - nonce, err := s.tree.GetNonce(ctx, address, l2Block.Root().Bytes()) + nonce, err := s.tree.GetNonce(ctx, address, root.Bytes()) if err != nil { return 0, err } @@ -109,1011 +92,40 @@ func (s *State) GetNonce(ctx context.Context, address common.Address, blockNumbe } // GetStorageAt from a given address -func (s *State) GetStorageAt(ctx context.Context, address common.Address, position *big.Int, blockNumber uint64, dbTx pgx.Tx) (*big.Int, error) { - l2Block, err := s.GetL2BlockByNumber(ctx, blockNumber, dbTx) - if err != nil { - return nil, err - } - - return s.tree.GetStorageAt(ctx, address, position, l2Block.Root().Bytes()) -} - -// EstimateGas for a transaction -func (s *State) EstimateGas(transaction *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, error) { - const ethTransferGas = 21000 - - var lowEnd uint64 - var highEnd uint64 - - ctx := context.Background() - - lastBatches, l2BlockStateRoot, err := s.PostgresStorage.GetLastNBatchesByL2BlockNumber(ctx, l2BlockNumber, two, dbTx) - if err != nil { - return 0, err - } - - // Get latest batch from the database to get GER and Timestamp - lastBatch := lastBatches[0] - - // Get batch before latest to get state root and local exit root - previousBatch := lastBatches[0] - if len(lastBatches) > 1 { - previousBatch = lastBatches[1] - } - - lowEnd, err = core.IntrinsicGas(transaction.Data(), transaction.AccessList(), s.isContractCreation(transaction), true, false) - if err != nil { - return 0, err - } - - if lowEnd == ethTransferGas && transaction.To() != nil { - code, err := s.tree.GetCode(ctx, *transaction.To(), l2BlockStateRoot.Bytes()) - if err != nil { - log.Warnf("error while getting transaction.to() code %v", err) - } else if len(code) == 0 { - return lowEnd, nil - } - } - - if transaction.Gas() != 0 && transaction.Gas() > lowEnd { - highEnd = transaction.Gas() - } else { - highEnd = s.cfg.MaxCumulativeGasUsed - } - - var availableBalance *big.Int - - if senderAddress != ZeroAddress { - senderBalance, err := s.tree.GetBalance(ctx, senderAddress, l2BlockStateRoot.Bytes()) - if err != nil { - if err == ErrNotFound { - senderBalance = big.NewInt(0) - } else { - return 0, err - } - } - - availableBalance = new(big.Int).Set(senderBalance) - - if transaction.Value() != nil { - if transaction.Value().Cmp(availableBalance) > 0 { - return 0, ErrInsufficientFunds - } - - availableBalance.Sub(availableBalance, transaction.Value()) - } - } - - if transaction.GasPrice().BitLen() != 0 && // Gas price has been set - availableBalance != nil && // Available balance is found - availableBalance.Cmp(big.NewInt(0)) > 0 { // Available balance > 0 - gasAllowance := new(big.Int).Div(availableBalance, transaction.GasPrice()) - - // Check the gas allowance for this account, make sure high end is capped to it - if gasAllowance.IsUint64() && highEnd > gasAllowance.Uint64() { - log.Debugf("Gas estimation high-end capped by allowance [%d]", gasAllowance.Uint64()) - highEnd = gasAllowance.Uint64() - } - } - - // Run the transaction with the specified gas value. - // Returns a status indicating if the transaction failed, if it was reverted and the accompanying error - testTransaction := func(gas uint64, shouldOmitErr bool) (bool, bool, uint64, error) { - var gasUsed uint64 - tx := types.NewTx(&types.LegacyTx{ - Nonce: transaction.Nonce(), - To: transaction.To(), - Value: transaction.Value(), - Gas: gas, - GasPrice: transaction.GasPrice(), - Data: transaction.Data(), - }) - - batchL2Data, err := EncodeUnsignedTransaction(*tx, s.cfg.ChainID) - if err != nil { - log.Errorf("error encoding unsigned transaction ", err) - return false, false, gasUsed, err - } - - // Create a batch to be sent to the executor - processBatchRequest := &pb.ProcessBatchRequest{ - BatchNum: lastBatch.BatchNumber + 1, - BatchL2Data: batchL2Data, - From: senderAddress.String(), - OldStateRoot: l2BlockStateRoot.Bytes(), - GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), - OldLocalExitRoot: previousBatch.LocalExitRoot.Bytes(), - EthTimestamp: uint64(lastBatch.Timestamp.Unix()), - Coinbase: lastBatch.Coinbase.String(), - UpdateMerkleTree: cFalse, - ChainId: s.cfg.ChainID, - } - - log.Debugf("EstimateGas[processBatchRequest.BatchNum]: %v", processBatchRequest.BatchNum) - // log.Debugf("EstimateGas[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) - log.Debugf("EstimateGas[processBatchRequest.From]: %v", processBatchRequest.From) - log.Debugf("EstimateGas[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) - log.Debugf("EstimateGas[processBatchRequest.GlobalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) - log.Debugf("EstimateGas[processBatchRequest.OldLocalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.OldLocalExitRoot)) - log.Debugf("EstimateGas[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) - log.Debugf("EstimateGas[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) - log.Debugf("EstimateGas[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) - log.Debugf("EstimateGas[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) - - txExecutionOnExecutorTime := time.Now() - processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) - gasUsed = processBatchResponse.Responses[0].GasUsed - log.Debugf("executor time: %vms", time.Since(txExecutionOnExecutorTime).Milliseconds()) - if err != nil { - log.Errorf("error processing unsigned transaction ", err) - return false, false, gasUsed, err - } - - // Check if an out of gas error happened during EVM execution - if processBatchResponse.Responses[0].Error != pb.Error(executor.ERROR_NO_ERROR) { - err := executor.Err(processBatchResponse.Responses[0].Error) - - if (isGasEVMError(err) || isGasApplyError(err)) && shouldOmitErr { - // Specifying the transaction failed, but not providing an error - // is an indication that a valid error occurred due to low gas, - // which will increase the lower bound for the search - return true, false, gasUsed, nil - } - - if isEVMRevertError(err) { - // The EVM reverted during execution, attempt to extract the - // error message and return it - return true, true, gasUsed, constructErrorFromRevert(err, processBatchResponse.Responses[0].ReturnValue) - } - - return true, false, gasUsed, err - } - - return false, false, gasUsed, nil - } - - txExecutions := []time.Duration{} - var totalExecutionTime time.Duration - - // Check if the highEnd is a good value to make the transaction pass - failed, reverted, gasUsed, err := testTransaction(highEnd, false) - log.Debugf("Estimate gas. Trying to execute TX with %v gas", highEnd) - if failed { - if reverted { - return 0, err - } - - // The transaction shouldn't fail, for whatever reason, at highEnd - return 0, fmt.Errorf( - "unable to apply transaction even for the highest gas limit %d: %w", - highEnd, - err, - ) - } - - if lowEnd < gasUsed { - lowEnd = gasUsed - } - - if gasUsed > 0 { - highEnd = (gasUsed * three) / uint64(two) - } - - // Start the binary search for the lowest possible gas price - for (lowEnd < highEnd) && (highEnd-lowEnd) > 4096 { - txExecutionStart := time.Now() - mid := (lowEnd + highEnd) / uint64(two) - - log.Debugf("Estimate gas. Trying to execute TX with %v gas", mid) - - failed, reverted, _, testErr := testTransaction(mid, true) - executionTime := time.Since(txExecutionStart) - totalExecutionTime += executionTime - txExecutions = append(txExecutions, executionTime) - if testErr != nil && !reverted { - // Reverts are ignored in the binary search, but are checked later on - // during the execution for the optimal gas limit found - return 0, testErr - } - - if failed { - // If the transaction failed => increase the gas - lowEnd = mid + 1 - } else { - // If the transaction didn't fail => make this ok value the high end - highEnd = mid - } - } - - executions := int64(len(txExecutions)) - if executions > 0 { - log.Debugf("EstimateGas executed the TX %v times", executions) - averageExecutionTime := totalExecutionTime.Milliseconds() / executions - log.Debugf("EstimateGas tx execution average time is %v milliseconds", averageExecutionTime) - } else { - log.Error("Estimate gas. Tx not executed") - } - return highEnd, nil -} - -// Checks if executor level valid gas errors occurred -func isGasApplyError(err error) bool { - return errors.Is(err, ErrNotEnoughIntrinsicGas) -} - -// Checks if EVM level valid gas errors occurred -func isGasEVMError(err error) bool { - return errors.Is(err, runtime.ErrOutOfGas) || - errors.Is(err, runtime.ErrCodeStoreOutOfGas) -} - -// Checks if the EVM reverted during execution -func isEVMRevertError(err error) bool { - return errors.Is(err, runtime.ErrExecutionReverted) -} - -// OpenBatch adds a new batch into the state, with the necessary data to start processing transactions within it. -// It's meant to be used by sequencers, since they don't necessarely know what transactions are going to be added -// in this batch yet. In other words it's the creation of a WIP batch. -// Note that this will add a batch with batch number N + 1, where N it's the greates batch number on the state. -func (s *State) OpenBatch(ctx context.Context, processingContext ProcessingContext, dbTx pgx.Tx) error { - if dbTx == nil { - return ErrDBTxNil - } - // Check if the batch that is being opened has batch num + 1 compared to the latest batch - lastBatchNum, err := s.PostgresStorage.GetLastBatchNumber(ctx, dbTx) - if err != nil { - return err - } - if lastBatchNum+1 != processingContext.BatchNumber { - return fmt.Errorf("unexpected batch number %v, should be %v", processingContext.BatchNumber, lastBatchNum+1) - } - // Check if last batch is closed - isLastBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, lastBatchNum, dbTx) - if err != nil { - return err - } - if !isLastBatchClosed { - return ErrLastBatchShouldBeClosed - } - // Check that timestamp is equal or greater compared to previous batch - prevTimestamp, err := s.GetLastBatchTime(ctx, dbTx) - if err != nil { - return err - } - if prevTimestamp.Unix() > processingContext.Timestamp.Unix() { - return ErrTimestampGE - } - return s.PostgresStorage.openBatch(ctx, processingContext, dbTx) -} - -// ProcessSequencerBatch is used by the sequencers to process transactions into an open batch -func (s *State) ProcessSequencerBatch(ctx context.Context, batchNumber uint64, txs []types.Transaction, dbTx pgx.Tx) (*ProcessBatchResponse, error) { - log.Debugf("*******************************************") - log.Debugf("ProcessSequencerBatch start") - batchL2Data, err := EncodeTransactions(txs) - if err != nil { - return nil, err - } - processBatchResponse, err := s.processBatch(ctx, batchNumber, batchL2Data, dbTx) - if err != nil { - return nil, err - } - result, err := convertToProcessBatchResponse(txs, processBatchResponse) - if err != nil { - return nil, err - } - log.Debugf("ProcessSequencerBatch end") - log.Debugf("*******************************************") - return result, nil -} - -// ExecuteBatch is used by the synchronizer to reprocess batches to compare generated state root vs stored one -func (s *State) ExecuteBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { - if dbTx == nil { - return nil, ErrDBTxNil - } - - // Get batch from the database to get GER and Timestamp - lastBatch, err := s.PostgresStorage.GetBatchByNumber(ctx, batchNumber, dbTx) - if err != nil { - return nil, err - } - - // Get previous batch to get state root and local exit root - previousBatch, err := s.PostgresStorage.GetBatchByNumber(ctx, batchNumber-1, dbTx) - if err != nil { - return nil, err - } - - // Create Batch - processBatchRequest := &pb.ProcessBatchRequest{ - BatchNum: lastBatch.BatchNumber, - Coinbase: lastBatch.Coinbase.String(), - BatchL2Data: batchL2Data, - OldStateRoot: previousBatch.StateRoot.Bytes(), - GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), - OldLocalExitRoot: previousBatch.LocalExitRoot.Bytes(), - EthTimestamp: uint64(lastBatch.Timestamp.Unix()), - UpdateMerkleTree: cFalse, - ChainId: s.cfg.ChainID, - } - - return s.executorClient.ProcessBatch(ctx, processBatchRequest) -} - -func (s *State) processBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { - if dbTx == nil { - return nil, ErrDBTxNil - } - lastBatches, err := s.PostgresStorage.GetLastNBatches(ctx, two, dbTx) - if err != nil { - return nil, err - } - - // Get latest batch from the database to get GER and Timestamp - lastBatch := lastBatches[0] - - // Get batch before latest to get state root and local exit root - previousBatch := lastBatches[0] - if len(lastBatches) > 1 { - previousBatch = lastBatches[1] - } - - isBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, batchNumber, dbTx) - if err != nil { - return nil, err - } - if isBatchClosed { - return nil, ErrBatchAlreadyClosed - } - - // Check provided batch number is the latest in db - if lastBatch.BatchNumber != batchNumber { - return nil, ErrInvalidBatchNumber - } - // Create Batch - processBatchRequest := &pb.ProcessBatchRequest{ - BatchNum: lastBatch.BatchNumber, - Coinbase: lastBatch.Coinbase.String(), - BatchL2Data: batchL2Data, - OldStateRoot: previousBatch.StateRoot.Bytes(), - GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), - OldLocalExitRoot: previousBatch.LocalExitRoot.Bytes(), - EthTimestamp: uint64(lastBatch.Timestamp.Unix()), - UpdateMerkleTree: cTrue, - ChainId: s.cfg.ChainID, - } - - // Send Batch to the Executor - log.Debugf("processBatch[processBatchRequest.BatchNum]: %v", processBatchRequest.BatchNum) - // log.Debugf("processBatch[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) - log.Debugf("processBatch[processBatchRequest.From]: %v", processBatchRequest.From) - log.Debugf("processBatch[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) - log.Debugf("processBatch[processBatchRequest.GlobalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) - log.Debugf("processBatch[processBatchRequest.OldLocalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.OldLocalExitRoot)) - log.Debugf("processBatch[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) - log.Debugf("processBatch[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) - log.Debugf("processBatch[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) - log.Debugf("processBatch[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) - now := time.Now() - res, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) - log.Infof("It took %v for the executor to process the request", time.Since(now)) - return res, err -} - -// StoreTransactions is used by the sequencer to add processed transactions into -// an open batch. If the batch already has txs, the processedTxs must be a super -// set of the existing ones, preserving order. -func (s *State) StoreTransactions(ctx context.Context, batchNumber uint64, processedTxs []*ProcessTransactionResponse, dbTx pgx.Tx) error { - if dbTx == nil { - return ErrDBTxNil - } - - // check existing txs vs parameter txs - existingTxs, err := s.GetTxsHashesByBatchNumber(ctx, batchNumber, dbTx) - if err != nil { - return err - } - if err := CheckSupersetBatchTransactions(existingTxs, processedTxs); err != nil { - return err - } - - // Check if last batch is closed. Note that it's assumed that only the latest batch can be open - isBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, batchNumber, dbTx) - if err != nil { - return err - } - if isBatchClosed { - return ErrBatchAlreadyClosed - } - - processingContext, err := s.GetProcessingContext(ctx, batchNumber, dbTx) - if err != nil { - return err - } - - firstTxToInsert := len(existingTxs) - - for i := firstTxToInsert; i < len(processedTxs); i++ { - processedTx := processedTxs[i] - // if the transaction has an intrinsic invalid tx error it means - // the transaction has not changed the state, so we don't store it - // and just move to the next - if errors.Is(processedTx.Error, runtime.ErrIntrinsicInvalidTransaction) { - continue - } - - lastL2Block, err := s.GetLastL2Block(ctx, dbTx) - if err != nil { - return err - } - - header := &types.Header{ - Number: new(big.Int).SetUint64(lastL2Block.Number().Uint64() + 1), - ParentHash: lastL2Block.Hash(), - Coinbase: processingContext.Coinbase, - Root: processedTx.StateRoot, - GasUsed: processedTx.GasUsed, - GasLimit: s.cfg.MaxCumulativeGasUsed, - Time: uint64(processingContext.Timestamp.Unix()), - } - transactions := []*types.Transaction{&processedTx.Tx} - - receipt := generateReceipt(header.Number, processedTx) - receipts := []*types.Receipt{receipt} - - // Create block to be able to calculate its hash - block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) - block.ReceivedAt = processingContext.Timestamp - - receipt.BlockHash = block.Hash() - - // Store L2 block and its transaction - if err := s.AddL2Block(ctx, batchNumber, block, receipts, dbTx); err != nil { - return err - } - } - return nil -} - -func (s *State) isBatchClosable(ctx context.Context, receipt ProcessingReceipt, dbTx pgx.Tx) error { - // Check if the batch that is being closed is the last batch - lastBatchNum, err := s.PostgresStorage.GetLastBatchNumber(ctx, dbTx) - if err != nil { - return err - } - if lastBatchNum != receipt.BatchNumber { - return fmt.Errorf("unexpected batch number %v, should be %v", receipt.BatchNumber, lastBatchNum) - } - // Check if last batch is closed - isLastBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, lastBatchNum, dbTx) - if err != nil { - return err - } - if isLastBatchClosed { - return ErrBatchAlreadyClosed - } - - return nil -} - -// closeSynchronizedBatch is used by Synchronizer to close the current batch. -func (s *State) closeSynchronizedBatch(ctx context.Context, receipt ProcessingReceipt, batchL2Data []byte, dbTx pgx.Tx) error { - if dbTx == nil { - return ErrDBTxNil - } - - err := s.isBatchClosable(ctx, receipt, dbTx) - if err != nil { - return err - } - - // TODO: Modification done to bypass situation detected during testnet testing - // Further analysis is needed - /* - if len(txs) == 0 { - return ErrClosingBatchWithoutTxs - } - */ - - // batchL2Data, err := EncodeTransactions(txs) - // if err != nil { - // return err - // } - - return s.PostgresStorage.closeBatch(ctx, receipt, batchL2Data, dbTx) -} - -// CloseBatch is used by sequencer to close the current batch. It will set the processing receipt and -// the raw txs data based on the txs included on that batch that are already in the state -func (s *State) CloseBatch(ctx context.Context, receipt ProcessingReceipt, dbTx pgx.Tx) error { - // TODO: differentiate the case where sequencer / sync calls the function so it's possible - // to use L2BatchData from L1 rather than from stored txs - if dbTx == nil { - return ErrDBTxNil - } - - err := s.isBatchClosable(ctx, receipt, dbTx) - if err != nil { - return err - } - - // Generate raw txs data - encodedTxsArray, err := s.GetEncodedTransactionsByBatchNumber(ctx, receipt.BatchNumber, dbTx) - if err != nil { - return err - } - if len(encodedTxsArray) == 0 { - return ErrClosingBatchWithoutTxs - } - txs := []types.Transaction{} - for i := 0; i < len(encodedTxsArray); i++ { - tx, err := DecodeTx(encodedTxsArray[i]) - if err != nil { - return err - } - txs = append(txs, *tx) +func (s *State) GetStorageAt(ctx context.Context, address common.Address, position *big.Int, root common.Hash) (*big.Int, error) { + if s.tree == nil { + return nil, ErrStateTreeNil } - batchL2Data, err := EncodeTransactions(txs) - if err != nil { - return err - } - - return s.PostgresStorage.closeBatch(ctx, receipt, batchL2Data, dbTx) + return s.tree.GetStorageAt(ctx, address, position, root.Bytes()) } -// ProcessAndStoreClosedBatch is used by the Synchronizer to add a closed batch into the data base -func (s *State) ProcessAndStoreClosedBatch(ctx context.Context, processingCtx ProcessingContext, encodedTxs []byte, dbTx pgx.Tx) error { - // Decode transactions - decodedTransactions, _, err := DecodeTxs(encodedTxs) - if err != nil { - log.Debugf("error decoding transactions: %w", err) - return err - } - - // Open the batch and process the txs - if dbTx == nil { - return ErrDBTxNil - } - if err := s.OpenBatch(ctx, processingCtx, dbTx); err != nil { - return err - } - processed, err := s.processBatch(ctx, processingCtx.BatchNumber, encodedTxs, dbTx) - if err != nil { - return err - } - - // Sanity check - if len(decodedTransactions) != len(processed.Responses) { - return fmt.Errorf("number of decoded (%d) and processed (%d) transactions do not match", len(decodedTransactions), len(processed.Responses)) - } - - // Filter unprocessed txs and decode txs to store metadata - // note that if the batch is not well encoded it will result in an empty batch (with no txs) - for i := 0; i < len(processed.Responses); i++ { - if !isProcessed(processed.Responses[i].Error) { - // Remove unprocessed tx - if i == len(processed.Responses)-1 { - processed.Responses = processed.Responses[:i] - decodedTransactions = decodedTransactions[:i] - } else { - processed.Responses = append(processed.Responses[:i], processed.Responses[i+1:]...) - decodedTransactions = append(decodedTransactions[:i], decodedTransactions[i+1:]...) - } - i-- - } - } - - processedBatch, err := convertToProcessBatchResponse(decodedTransactions, processed) - if err != nil { - return err - } - // Store processed txs into the batch - err = s.StoreTransactions(ctx, processingCtx.BatchNumber, processedBatch.Responses, dbTx) +// GetLastStateRoot returns the latest state root +func (s *State) GetLastStateRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) { + lastBlockHeader, err := s.GetLastL2BlockHeader(ctx, dbTx) if err != nil { - return err + return common.Hash{}, err } - - // Close batch - return s.closeSynchronizedBatch(ctx, ProcessingReceipt{ - BatchNumber: processingCtx.BatchNumber, - StateRoot: processedBatch.NewStateRoot, - LocalExitRoot: processedBatch.NewLocalExitRoot, - }, encodedTxs, dbTx) + return lastBlockHeader.Root, nil } -// GetLastBatch gets latest batch (closed or not) on the data base -func (s *State) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*Batch, error) { - batches, err := s.PostgresStorage.GetLastNBatches(ctx, 1, dbTx) - if err != nil { - return nil, err +// GetBalanceByStateRoot gets balance from the MT Service using the provided state root +func (s *State) GetBalanceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + if s.tree == nil { + return nil, ErrStateTreeNil } - if len(batches) == 0 { - return nil, ErrNotFound + balance, err := s.tree.GetBalance(ctx, address, root.Bytes()) + if err != nil && balance == nil { + balance = big.NewInt(0) } - return batches[0], nil + return balance, err } -// DebugTransaction re-executes a tx to generate its trace -func (s *State) DebugTransaction(ctx context.Context, transactionHash common.Hash, tracer string, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { - result := new(runtime.ExecutionResult) - - // Get the transaction - tx, err := s.GetTransactionByHash(ctx, transactionHash, dbTx) - if err != nil { - return nil, err - } - - // Get batch including the transaction - batch, err := s.GetBatchByTxHash(ctx, transactionHash, dbTx) - if err != nil { - return nil, err +// GetNonceByStateRoot gets nonce from the MT Service using the provided state root +func (s *State) GetNonceByStateRoot(ctx context.Context, address common.Address, root common.Hash) (*big.Int, error) { + if s.tree == nil { + return nil, ErrStateTreeNil } - - // The previous batch to get OldStateRoot and GlobalExitRoot - pBatch, err := s.GetBatchByNumber(ctx, batch.BatchNumber-1, dbTx) - if err != nil { - return nil, err - } - - batchL2Data := batch.BatchL2Data - if batchL2Data == nil { - txs, err := s.GetTransactionsByBatchNumber(ctx, batch.BatchNumber, dbTx) - if err != nil { - return nil, err - } - - for _, tx := range txs { - log.Debugf(tx.Hash().String()) - } - - batchL2Data, err = EncodeTransactions(txs) - if err != nil { - return nil, err - } - } - - // Create Batch - processBatchRequest := &pb.ProcessBatchRequest{ - BatchNum: batch.BatchNumber, - BatchL2Data: batchL2Data, - OldStateRoot: pBatch.StateRoot.Bytes(), - GlobalExitRoot: batch.GlobalExitRoot.Bytes(), - OldLocalExitRoot: pBatch.LocalExitRoot.Bytes(), - EthTimestamp: uint64(batch.Timestamp.Unix()), - Coinbase: batch.Coinbase.String(), - UpdateMerkleTree: cFalse, - TxHashToGenerateCallTrace: transactionHash.Bytes(), - } - - // Send Batch to the Executor - startTime := time.Now() - processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) - if err != nil { - return nil, err - } - endTime := time.Now() - - txs, _, err := DecodeTxs(batchL2Data) - if err != nil { - return nil, err - } - - for _, tx := range txs { - log.Debugf(tx.Hash().String()) - } - - convertedResponse, err := convertToProcessBatchResponse(txs, processBatchResponse) - if err != nil { - return nil, err - } - - var response *ProcessTransactionResponse - - // Get the response for the tx - for _, response = range convertedResponse.Responses { - log.Debugf(response.TxHash.String()) - if response.TxHash == transactionHash { - break - } - } - - // Sanity check - if response.TxHash != transactionHash { - return nil, fmt.Errorf("tx hash not found in executor response") - } - - result.CreateAddress = response.CreateAddress - result.GasLeft = response.GasLeft - result.GasUsed = response.GasUsed - result.ReturnValue = response.ReturnValue - result.StateRoot = response.StateRoot.Bytes() - result.StructLogs = response.ExecutionTrace - - if tracer == "" { - return result, nil - } - - // Parse the executor-like trace using the FakeEVM - jsTracer, err := js.NewJsTracer(tracer, new(tracers.Context)) - if err != nil { - log.Errorf("debug transaction: failed to create jsTracer, err: %v", err) - return nil, fmt.Errorf("failed to create jsTracer, err: %v", err) - } - - context := instrumentation.Context{} - - // Fill trace context - if tx.To() == nil { - context.Type = "CREATE" - context.To = result.CreateAddress.Hex() - } else { - context.Type = "CALL" - context.To = tx.To().Hex() - } - - senderAddress, err := GetSender(*tx) - if err != nil { - return nil, err - } - - context.From = senderAddress.String() - context.Input = "0x" + hex.EncodeToString(tx.Data()) - context.Gas = strconv.FormatUint(tx.Gas(), encoding.Base10) - context.Value = tx.Value().String() - context.Output = "0x" + hex.EncodeToString(result.ReturnValue) - context.GasPrice = tx.GasPrice().String() - context.OldStateRoot = batch.StateRoot.String() - context.Time = uint64(endTime.Sub(startTime)) - context.GasUsed = strconv.FormatUint(result.GasUsed, encoding.Base10) - - result.ExecutorTrace.Context = context - - gasPrice, ok := new(big.Int).SetString(context.GasPrice, encoding.Base10) - if !ok { - log.Errorf("debug transaction: failed to parse gasPrice") - return nil, fmt.Errorf("failed to parse gasPrice") - } - - env := fakevm.NewFakeEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: gasPrice}, params.TestChainConfig, fakevm.Config{Debug: true, Tracer: jsTracer}) - fakeDB := &FakeDB{State: s, stateRoot: batch.StateRoot.Bytes()} - env.SetStateDB(fakeDB) - - traceResult, err := s.ParseTheTraceUsingTheTracer(env, result.ExecutorTrace, jsTracer) - if err != nil { - log.Errorf("debug transaction: failed parse the trace using the tracer: %v", err) - return nil, fmt.Errorf("failed parse the trace using the tracer: %v", err) - } - - result.ExecutorTraceResult = traceResult - - return result, nil -} - -// ParseTheTraceUsingTheTracer parses the given trace with the given tracer. -func (s *State) ParseTheTraceUsingTheTracer(env *fakevm.FakeEVM, trace instrumentation.ExecutorTrace, jsTracer tracers.Tracer) (json.RawMessage, error) { - var previousDepth int - var previousOpcode string - var stateRoot []byte - - contextGas, ok := new(big.Int).SetString(trace.Context.Gas, encoding.Base10) - if !ok { - log.Debugf("error while parsing contextGas") - return nil, ErrParsingExecutorTrace - } - value, ok := new(big.Int).SetString(trace.Context.Value, encoding.Base10) - if !ok { - log.Debugf("error while parsing value") - return nil, ErrParsingExecutorTrace - } - - jsTracer.CaptureTxStart(contextGas.Uint64()) - jsTracer.CaptureStart(env, common.HexToAddress(trace.Context.From), common.HexToAddress(trace.Context.To), trace.Context.Type == "CREATE", common.Hex2Bytes(strings.TrimLeft(trace.Context.Input, "0x")), contextGas.Uint64(), value) - - stack := fakevm.Newstack() - memory := fakevm.NewMemory() - - bigStateRoot, ok := new(big.Int).SetString(trace.Context.OldStateRoot, 0) - if !ok { - log.Debugf("error while parsing context oldStateRoot") - return nil, ErrParsingExecutorTrace - } - stateRoot = bigStateRoot.Bytes() - env.StateDB.SetStateRoot(stateRoot) - - for i, step := range trace.Steps { - gas, ok := new(big.Int).SetString(step.Gas, encoding.Base10) - if !ok { - log.Debugf("error while parsing step gas") - return nil, ErrParsingExecutorTrace - } - - gasCost, ok := new(big.Int).SetString(step.GasCost, encoding.Base10) - if !ok { - log.Debugf("error while parsing step gasCost") - return nil, ErrParsingExecutorTrace - } - - value, ok := new(big.Int).SetString(step.Contract.Value, encoding.Base10) - if !ok { - log.Debugf("error while parsing step value") - return nil, ErrParsingExecutorTrace - } - - op, ok := new(big.Int).SetString(step.Op, 0) - if !ok { - log.Debugf("error while parsing step op") - return nil, ErrParsingExecutorTrace - } - - scope := &fakevm.ScopeContext{ - Contract: vm.NewContract(fakevm.NewAccount(common.HexToAddress(step.Contract.Caller)), fakevm.NewAccount(common.HexToAddress(step.Contract.Address)), value, gas.Uint64()), - Memory: memory, - Stack: stack, - } - - codeAddr := common.HexToAddress(step.Contract.Address) - scope.Contract.CodeAddr = &codeAddr - - opcode := vm.OpCode(op.Uint64()).String() - - if previousOpcode == "CALL" && step.Pc != 0 { - jsTracer.CaptureExit(common.Hex2Bytes(step.ReturnData), gasCost.Uint64(), fmt.Errorf(step.Error)) - } - - if opcode != "CALL" || trace.Steps[i+1].Pc == 0 { - if step.Error != "" { - err := fmt.Errorf(step.Error) - jsTracer.CaptureFault(step.Pc, vm.OpCode(op.Uint64()), gas.Uint64(), gasCost.Uint64(), scope, step.Depth, err) - } else { - jsTracer.CaptureState(step.Pc, vm.OpCode(op.Uint64()), gas.Uint64(), gasCost.Uint64(), scope, common.Hex2Bytes(strings.TrimLeft(step.ReturnData, "0x")), step.Depth, nil) - } - } - - if opcode == "CREATE" || opcode == "CREATE2" || opcode == "CALL" || opcode == "CALLCODE" || opcode == "DELEGATECALL" || opcode == "STATICCALL" || opcode == "SELFDESTRUCT" { - jsTracer.CaptureEnter(vm.OpCode(op.Uint64()), common.HexToAddress(step.Contract.Caller), common.HexToAddress(step.Contract.Address), common.Hex2Bytes(strings.TrimLeft(step.Contract.Input, "0x")), gas.Uint64(), value) - if step.OpCode == "SELFDESTRUCT" { - jsTracer.CaptureExit(common.Hex2Bytes(step.ReturnData), gasCost.Uint64(), fmt.Errorf(step.Error)) - } - } - - // Set Memory - if len(step.Memory) > 0 { - memory.Resize(uint64(fakevm.MemoryItemSize*len(step.Memory) + zkEVMReservedMemorySize)) - for offset, memoryContent := range step.Memory { - memory.Set(uint64((offset*fakevm.MemoryItemSize)+zkEVMReservedMemorySize), uint64(fakevm.MemoryItemSize), common.Hex2Bytes(memoryContent)) - } - } else { - memory = fakevm.NewMemory() - } - - // Set Stack - stack = fakevm.Newstack() - for _, stackContent := range step.Stack { - valueBigInt, ok := new(big.Int).SetString(stackContent, 0) - if !ok { - log.Debugf("error while parsing stack valueBigInt") - return nil, ErrParsingExecutorTrace - } - value, _ := uint256.FromBig(valueBigInt) - stack.Push(value) - } - - // Returning from a call or create - if previousDepth > step.Depth { - jsTracer.CaptureExit(common.Hex2Bytes(step.ReturnData), gasCost.Uint64(), fmt.Errorf(step.Error)) - } - - // Set StateRoot - bigStateRoot, ok := new(big.Int).SetString(step.StateRoot, 0) - if !ok { - log.Debugf("error while parsing step stateRoot") - return nil, ErrParsingExecutorTrace - } - - stateRoot = bigStateRoot.Bytes() - env.StateDB.SetStateRoot(stateRoot) - previousDepth = step.Depth - previousOpcode = step.OpCode - } - - gasUsed, ok := new(big.Int).SetString(trace.Context.GasUsed, encoding.Base10) - if !ok { - log.Debugf("error while parsing gasUsed") - return nil, ErrParsingExecutorTrace - } - - jsTracer.CaptureTxEnd(gasUsed.Uint64()) - jsTracer.CaptureEnd(common.Hex2Bytes(trace.Context.Output), gasUsed.Uint64(), time.Duration(trace.Context.Time), nil) - - return jsTracer.GetResult() -} - -// ProcessUnsignedTransaction processes the given unsigned transaction. -func (s *State) ProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) *runtime.ExecutionResult { - result := new(runtime.ExecutionResult) - - lastBatches, l2BlockStateRoot, err := s.PostgresStorage.GetLastNBatchesByL2BlockNumber(ctx, l2BlockNumber, two, dbTx) - if err != nil { - result.Err = err - return result - } - - // Get latest batch from the database to get GER and Timestamp - lastBatch := lastBatches[0] - - // Get batch before latest to get state root and local exit root - previousBatch := lastBatches[0] - if len(lastBatches) > 1 { - previousBatch = lastBatches[1] - } - - batchL2Data, err := EncodeUnsignedTransaction(*tx, s.cfg.ChainID) - if err != nil { - log.Errorf("error encoding unsigned transaction ", err) - result.Err = err - return result - } - - // Create Batch - processBatchRequest := &pb.ProcessBatchRequest{ - BatchNum: lastBatch.BatchNumber + 1, - BatchL2Data: batchL2Data, - From: senderAddress.String(), - OldStateRoot: l2BlockStateRoot.Bytes(), - GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), - OldLocalExitRoot: previousBatch.LocalExitRoot.Bytes(), - EthTimestamp: uint64(lastBatch.Timestamp.Unix()), - Coinbase: lastBatch.Coinbase.String(), - UpdateMerkleTree: cFalse, - ChainId: s.cfg.ChainID, - } - - if noZKEVMCounters { - processBatchRequest.NoCounters = cTrue - } - - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.BatchNum]: %v", processBatchRequest.BatchNum) - // log.Debugf("ProcessUnsignedTransaction[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.From]: %v", processBatchRequest.From) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.GlobalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.OldLocalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.OldLocalExitRoot)) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) - log.Debugf("ProcessUnsignedTransaction[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) - - // Send Batch to the Executor - processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) - if err != nil { - log.Errorf("error processing unsigned transaction ", err) - result.Err = err - return result - } - response, err := convertToProcessBatchResponse([]types.Transaction{*tx}, processBatchResponse) - if err != nil { - result.Err = err - return result - } - // Todo populate result - r := response.Responses[0] - result.ReturnValue = r.ReturnValue - result.GasLeft = r.GasLeft - result.GasUsed = r.GasUsed - result.CreateAddress = r.CreateAddress - result.StateRoot = r.StateRoot.Bytes() - if processBatchResponse.Responses[0].Error != pb.Error(executor.ERROR_NO_ERROR) { - err := executor.Err(processBatchResponse.Responses[0].Error) - if isEVMRevertError(err) { - result.Err = constructErrorFromRevert(err, processBatchResponse.Responses[0].ReturnValue) - } else { - result.Err = err - } - } - - return result + return s.tree.GetNonce(ctx, address, root.Bytes()) } // GetTree returns State inner tree @@ -1121,172 +133,10 @@ func (s *State) GetTree() *merkletree.StateTree { return s.tree } -// SetGenesis populates state with genesis information -func (s *State) SetGenesis(ctx context.Context, block Block, genesis Genesis, dbTx pgx.Tx) ([]byte, error) { - var ( - root common.Hash - newRoot []byte - err error - ) - if dbTx == nil { - return newRoot, ErrDBTxNil - } - - for _, action := range genesis.Actions { - address := common.HexToAddress(action.Address) - switch action.Type { - case int(merkletree.LeafTypeBalance): - balance, err := encoding.DecodeBigIntHexOrDecimal(action.Value) - if err != nil { - return newRoot, err - } - newRoot, _, err = s.tree.SetBalance(ctx, address, balance, newRoot) - if err != nil { - return newRoot, err - } - case int(merkletree.LeafTypeNonce): - nonce, err := encoding.DecodeBigIntHexOrDecimal(action.Value) - if err != nil { - return newRoot, err - } - newRoot, _, err = s.tree.SetNonce(ctx, address, nonce, newRoot) - if err != nil { - return newRoot, err - } - case int(merkletree.LeafTypeCode): - code, err := hex.DecodeHex(action.Bytecode) - if err != nil { - return newRoot, fmt.Errorf("Could not decode SC bytecode for address %q: %v", address, err) - } - newRoot, _, err = s.tree.SetCode(ctx, address, code, newRoot) - if err != nil { - return newRoot, err - } - case int(merkletree.LeafTypeStorage): - // Parse position and value - positionBI, err := encoding.DecodeBigIntHexOrDecimal(action.StoragePosition) - if err != nil { - return newRoot, err - } - valueBI, err := encoding.DecodeBigIntHexOrDecimal(action.Value) - if err != nil { - return newRoot, err - } - // Store - newRoot, _, err = s.tree.SetStorageAt(ctx, address, positionBI, valueBI, newRoot) - if err != nil { - return newRoot, err - } - case int(merkletree.LeafTypeSCLength): - log.Debug("Skipped genesis action of type merkletree.LeafTypeSCLength, these actions will be handled as part of merkletree.LeafTypeCode actions") - default: - return newRoot, fmt.Errorf("Unknown genesis action type %q", action.Type) - } - } - - root.SetBytes(newRoot) - - // store L1 block related to genesis batch - err = s.AddBlock(ctx, &block, dbTx) - if err != nil { - return newRoot, err - } - - // store genesis batch - batch := Batch{ - BatchNumber: 0, - Coinbase: ZeroAddress, - BatchL2Data: nil, - StateRoot: root, - LocalExitRoot: ZeroHash, - Timestamp: block.ReceivedAt, - Transactions: []types.Transaction{}, - GlobalExitRoot: ZeroHash, - } - - err = s.storeGenesisBatch(ctx, batch, dbTx) - if err != nil { - return newRoot, err - } - - // mark the genesis batch as virtualized - virtualBatch := &VirtualBatch{ - BatchNumber: batch.BatchNumber, - TxHash: ZeroHash, - Coinbase: ZeroAddress, - BlockNumber: block.BlockNumber, - } - err = s.AddVirtualBatch(ctx, virtualBatch, dbTx) - if err != nil { - return newRoot, err - } - - // mark the genesis batch as verified/consolidated - verifiedBatch := &VerifiedBatch{ - BatchNumber: batch.BatchNumber, - TxHash: ZeroHash, - Aggregator: ZeroAddress, - BlockNumber: block.BlockNumber, - } - err = s.AddVerifiedBatch(ctx, verifiedBatch, dbTx) - if err != nil { - return newRoot, err - } - - // store L2 genesis block - header := &types.Header{ - Number: big.NewInt(0), - ParentHash: ZeroHash, - Coinbase: ZeroAddress, - Root: root, - Time: uint64(block.ReceivedAt.Unix()), - } - rootHex := root.Hex() - log.Info("Genesis root ", rootHex) - l2Block := types.NewBlock(header, []*types.Transaction{}, []*types.Header{}, []*types.Receipt{}, &trie.StackTrie{}) - l2Block.ReceivedAt = block.ReceivedAt - - return newRoot, s.AddL2Block(ctx, batch.BatchNumber, l2Block, []*types.Receipt{}, dbTx) -} - -// CheckSupersetBatchTransactions verifies that processedTransactions is a -// superset of existingTxs and that the existing txs have the same order, -// returns a non-nil error if that is not the case. -func CheckSupersetBatchTransactions(existingTxHashes []common.Hash, processedTxs []*ProcessTransactionResponse) error { - if len(existingTxHashes) > len(processedTxs) { - return ErrExistingTxGreaterThanProcessedTx - } - for i, existingTxHash := range existingTxHashes { - if existingTxHash != processedTxs[i].Tx.Hash() { - return ErrOutOfOrderProcessedTx - } - } - return nil -} - -// isContractCreation checks if the tx is a contract creation -func (s *State) isContractCreation(tx *types.Transaction) bool { - return tx.To() == nil && len(tx.Data()) > 0 -} - -// DetermineProcessedTransactions splits the given tx process responses -// returning a slice with only processed and a map unprocessed txs -// respectively. -func DetermineProcessedTransactions(responses []*ProcessTransactionResponse) ( - []*ProcessTransactionResponse, []string, map[string]*ProcessTransactionResponse, []string) { - processedTxResponses := []*ProcessTransactionResponse{} - processedTxsHashes := []string{} - unprocessedTxResponses := map[string]*ProcessTransactionResponse{} - unprocessedTxsHashes := []string{} - for _, response := range responses { - if response.IsProcessed { - processedTxResponses = append(processedTxResponses, response) - processedTxsHashes = append(processedTxsHashes, response.TxHash.String()) - } else { - log.Infof("Tx %s has not been processed", response.TxHash) - unprocessedTxResponses[response.TxHash.String()] = response - unprocessedTxsHashes = append(unprocessedTxsHashes, response.TxHash.String()) - } +// FlushMerkleTree persists updates in the Merkle tree +func (s *State) FlushMerkleTree(ctx context.Context) error { + if s.tree == nil { + return ErrStateTreeNil } - return processedTxResponses, processedTxsHashes, unprocessedTxResponses, unprocessedTxsHashes + return s.tree.Flush(ctx) } diff --git a/state/state_test.go b/state/state_test.go index 49c4f7fd4d..a31c0fee30 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -4,7 +4,8 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" + "math" "math/big" "os" "path/filepath" @@ -15,19 +16,26 @@ import ( "github.com/0xPolygonHermez/zkevm-node/db" "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" mtDBclientpb "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" executorclientpb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Counter" "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/0xPolygonHermez/zkevm-node/test/operations" "github.com/0xPolygonHermez/zkevm-node/test/testutils" "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/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/jackc/pgx/v4/pgxpool" @@ -50,10 +58,24 @@ var ( stateCfg = state.Config{ MaxCumulativeGasUsed: 800000, ChainID: 1000, - } + ForkIDIntervals: []state.ForkIDInterval{{ + FromBatchNumber: 0, + ToBatchNumber: math.MaxUint64, + ForkId: 0, + Version: "", + }}, + } + forkID uint64 = 2 executorClient executorclientpb.ExecutorServiceClient mtDBServiceClient mtDBclientpb.StateDBServiceClient executorClientConn, mtDBClientConn *grpc.ClientConn + batchResources = state.BatchResources{ + ZKCounters: state.ZKCounters{ + UsedKeccakHashes: 1, + }, + Bytes: 1, + } + closingReason = state.GlobalExitRootDeadlineClosingReason ) func TestMain(m *testing.M) { @@ -89,7 +111,13 @@ func TestMain(m *testing.M) { stateTree = merkletree.NewStateTree(mtDBServiceClient) - testState = state.NewState(stateCfg, state.NewPostgresStorage(stateDb), executorClient, stateTree) + eventStorage, err := nileventstorage.NewNilEventStorage() + if err != nil { + panic(err) + } + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + testState = state.NewState(stateCfg, state.NewPostgresStorage(stateDb), executorClient, stateTree, eventLog) result := m.Run() @@ -145,12 +173,12 @@ func TestProcessCloseBatch(t *testing.T) { // BatchNumber: 1, // Coinbase: common.HexToAddress("1"), // Timestamp: time.Now().UTC(), - // GlobalExitRoot: common.HexToHash("a"), + // globalExitRoot: common.HexToHash("a"), // } // Txs for batch #1 // rawTxs := "f84901843b9aca00827b0c945fbdb2315678afecb367f032d93f642f64180aa380a46057361d00000000000000000000000000000000000000000000000000000000000000048203e9808073efe1fa2d3e27f26f32208550ea9b0274d49050b816cadab05a771f4275d0242fd5d92b3fb89575c070e6c930587c520ee65a3aa8cfe382fcad20421bf51d621c" //TODO Finish and fix this test - // err = testState.ProcessAndStoreClosedBatch(ctx, processingCtx1, common.Hex2Bytes(rawTxs), dbTx) + // err = testState.ProcessAndStoreClosedBatch(ctx, processingCtx1, common.Hex2Bytes(rawTxs), dbTx, state.SynchronizerCallerLabel) // require.NoError(t, err) require.NoError(t, dbTx.Commit(ctx)) } @@ -188,12 +216,14 @@ func TestOpenCloseBatch(t *testing.T) { assert.Equal(t, state.ErrLastBatchShouldBeClosed, err) // Fail closing batch #1 (it has no txs yet) receipt1 := state.ProcessingReceipt{ - BatchNumber: 1, - StateRoot: common.HexToHash("1"), - LocalExitRoot: common.HexToHash("1"), + BatchNumber: 1, + StateRoot: common.HexToHash("1"), + LocalExitRoot: common.HexToHash("1"), + ClosingReason: closingReason, + BatchResources: batchResources, } err = testState.CloseBatch(ctx, receipt1, dbTx) - require.Equal(t, state.ErrClosingBatchWithoutTxs, err) + require.NoError(t, err) require.NoError(t, dbTx.Rollback(ctx)) dbTx, err = testState.BeginStateTransaction(ctx) require.NoError(t, err) @@ -210,6 +240,11 @@ func TestOpenCloseBatch(t *testing.T) { Tx: tx2, }, } + + data, err := state.EncodeTransactions([]types.Transaction{tx1, tx2}) + require.NoError(t, err) + receipt1.BatchL2Data = data + err = testState.StoreTransactions(ctx, 1, txsBatch1, dbTx) require.NoError(t, err) // Close batch #1 @@ -226,7 +261,7 @@ func TestOpenCloseBatch(t *testing.T) { GlobalExitRoot: common.HexToHash("c"), } err = testState.OpenBatch(ctx, processingCtx3, dbTx) - require.True(t, strings.Contains(err.Error(), "unexpected batch")) + require.ErrorIs(t, err, state.ErrUnexpectedBatch) // Fail opening batch #2 (invalid timestamp) processingCtx2.Timestamp = processingCtx1.Timestamp.Add(-1 * time.Second) err = testState.OpenBatch(ctx, processingCtx2, dbTx) @@ -261,42 +296,6 @@ func assertBatch(t *testing.T, expected, actual state.Batch) { assert.Equal(t, expected, actual) } -func TestAddGlobalExitRoot(t *testing.T) { - // Init database instance - initOrResetDB() - - ctx := context.Background() - fmt.Println("db: ", stateDb) - tx, err := testState.BeginStateTransaction(ctx) - require.NoError(t, err) - block := &state.Block{ - BlockNumber: 1, - BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - ReceivedAt: time.Now(), - } - err = testState.AddBlock(ctx, block, tx) - assert.NoError(t, err) - globalExitRoot := state.GlobalExitRoot{ - BlockNumber: 1, - GlobalExitRootNum: big.NewInt(2), - MainnetExitRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - RollupExitRoot: common.HexToHash("0x30a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0"), - GlobalExitRoot: common.HexToHash("0x40a885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9a0"), - } - err = testState.AddGlobalExitRoot(ctx, &globalExitRoot, tx) - require.NoError(t, err) - exit, err := testState.GetLatestGlobalExitRoot(ctx, tx) - require.NoError(t, err) - err = tx.Commit(ctx) - require.NoError(t, err) - assert.Equal(t, globalExitRoot.BlockNumber, exit.BlockNumber) - assert.Equal(t, globalExitRoot.GlobalExitRootNum, exit.GlobalExitRootNum) - assert.Equal(t, globalExitRoot.MainnetExitRoot, exit.MainnetExitRoot) - assert.Equal(t, globalExitRoot.RollupExitRoot, exit.RollupExitRoot) - assert.Equal(t, globalExitRoot.GlobalExitRoot, exit.GlobalExitRoot) -} - func TestAddForcedBatch(t *testing.T) { // Init database instance initOrResetDB() @@ -314,11 +313,9 @@ func TestAddForcedBatch(t *testing.T) { assert.NoError(t, err) b := common.Hex2Bytes("0x617b3a3528F9") assert.NoError(t, err) - var bN uint64 = 3 forcedBatch := state.ForcedBatch{ BlockNumber: 1, ForcedBatchNumber: 2, - BatchNumber: &bN, GlobalExitRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), Sequencer: common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D"), RawTxsData: b, @@ -331,7 +328,6 @@ func TestAddForcedBatch(t *testing.T) { err = tx.Commit(ctx) require.NoError(t, err) assert.Equal(t, forcedBatch.BlockNumber, fb.BlockNumber) - assert.Equal(t, forcedBatch.BatchNumber, fb.BatchNumber) assert.Equal(t, forcedBatch.ForcedBatchNumber, fb.ForcedBatchNumber) assert.NotEqual(t, time.Time{}, fb.ForcedAt) assert.Equal(t, forcedBatch.GlobalExitRoot, fb.GlobalExitRoot) @@ -342,7 +338,6 @@ func TestAddForcedBatch(t *testing.T) { forcedBatch = state.ForcedBatch{ BlockNumber: 1, ForcedBatchNumber: 3, - BatchNumber: nil, GlobalExitRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), Sequencer: common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D"), RawTxsData: b, @@ -350,23 +345,25 @@ func TestAddForcedBatch(t *testing.T) { } err = testState.AddForcedBatch(ctx, &forcedBatch, tx) require.NoError(t, err) + + _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num, forced_batch_num) VALUES (2, 2)") + assert.NoError(t, err) + virtualBatch := state.VirtualBatch{ + BlockNumber: 1, + BatchNumber: 2, + TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), + Coinbase: common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D"), + } + err = testState.AddVirtualBatch(ctx, &virtualBatch, tx) + require.NoError(t, err) + batches, err := testState.GetNextForcedBatches(ctx, 1, tx) require.NoError(t, err) - require.NoError(t, tx.Commit(ctx)) assert.Equal(t, forcedBatch.BlockNumber, batches[0].BlockNumber) - assert.Equal(t, forcedBatch.BatchNumber, batches[0].BatchNumber) assert.Equal(t, forcedBatch.ForcedBatchNumber, batches[0].ForcedBatchNumber) assert.NotEqual(t, time.Time{}, batches[0].ForcedAt) assert.Equal(t, forcedBatch.GlobalExitRoot, batches[0].GlobalExitRoot) assert.Equal(t, forcedBatch.RawTxsData, batches[0].RawTxsData) - // Test AddBatchNumberInForcedBatch - tx, err = testState.BeginStateTransaction(ctx) - require.NoError(t, err) - err = testState.AddBatchNumberInForcedBatch(ctx, 3, 2, tx) - require.NoError(t, err) - fb, err = testState.GetForcedBatch(ctx, 3, tx) - require.NoError(t, err) - assert.Equal(t, uint64(2), *fb.BatchNumber) require.NoError(t, tx.Commit(ctx)) } @@ -445,14 +442,14 @@ func TestGetTxsHashesToDelete(t *testing.T) { require.NoError(t, err) require.NoError(t, tx.Commit(ctx)) - _, err = testState.Exec(ctx, "INSERT INTO state.l2block (block_num, block_hash, received_at, batch_num) VALUES ($1, $2, $3, $4)", 1, "0x423", time.Now(), 1) + _, err = testState.Exec(ctx, "INSERT INTO state.l2block (block_num, block_hash, received_at, batch_num, created_at) VALUES ($1, $2, $3, $4, $5)", 1, "0x423", time.Now(), 1, time.Now().UTC()) require.NoError(t, err) l2Tx1 := types.NewTransaction(1, common.Address{}, big.NewInt(10), 21000, big.NewInt(1), []byte{}) _, err = testState.Exec(ctx, "INSERT INTO state.transaction (l2_block_num, encoded, hash) VALUES ($1, $2, $3)", virtualBatch1.BatchNumber, fmt.Sprintf("encoded-%d", virtualBatch1.BatchNumber), l2Tx1.Hash().Hex()) require.NoError(t, err) - _, err = testState.Exec(ctx, "INSERT INTO state.l2block (block_num, block_hash, received_at, batch_num) VALUES ($1, $2, $3, $4)", 2, "0x423", time.Now(), 2) + _, err = testState.Exec(ctx, "INSERT INTO state.l2block (block_num, block_hash, received_at, batch_num, created_at) VALUES ($1, $2, $3, $4, $5)", 2, "0x423", time.Now(), 2, time.Now().UTC()) require.NoError(t, err) l2Tx2 := types.NewTransaction(2, common.Address{}, big.NewInt(10), 21000, big.NewInt(1), []byte{}) _, err = testState.Exec(ctx, "INSERT INTO state.transaction (l2_block_num, encoded, hash) VALUES ($1, $2, $3)", @@ -462,54 +459,6 @@ func TestGetTxsHashesToDelete(t *testing.T) { require.NoError(t, err) require.Equal(t, l2Tx1.Hash().Hex(), txHashes[0].Hex()) } -func TestVerifiedBatch(t *testing.T) { - initOrResetDB() - - ctx := context.Background() - dbTx, err := testState.BeginStateTransaction(ctx) - require.NoError(t, err) - - block := &state.Block{ - BlockNumber: 1, - BlockHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - ParentHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - ReceivedAt: time.Now(), - } - err = testState.AddBlock(ctx, block, dbTx) - assert.NoError(t, err) - //require.NoError(t, tx.Commit(ctx)) - - lastBlock, err := testState.GetLastBlock(ctx, dbTx) - assert.NoError(t, err) - assert.Equal(t, uint64(1), lastBlock.BlockNumber) - - _, err = testState.PostgresStorage.Exec(ctx, "INSERT INTO state.batch (batch_num) VALUES (1)") - - require.NoError(t, err) - virtualBatch := state.VirtualBatch{ - BlockNumber: 1, - BatchNumber: 1, - TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - } - err = testState.AddVirtualBatch(ctx, &virtualBatch, dbTx) - require.NoError(t, err) - expectedVerifiedBatch := state.VerifiedBatch{ - BlockNumber: 1, - BatchNumber: 1, - Aggregator: common.HexToAddress("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - TxHash: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9f1"), - } - err = testState.AddVerifiedBatch(ctx, &expectedVerifiedBatch, dbTx) - require.NoError(t, err) - - // Step to create done, retrieve it - - actualVerifiedBatch, err := testState.GetVerifiedBatch(ctx, 1, dbTx) - require.NoError(t, err) - require.Equal(t, expectedVerifiedBatch, *actualVerifiedBatch) - - require.NoError(t, dbTx.Commit(ctx)) -} func TestExecuteTransaction(t *testing.T) { var chainIDSequencer = new(big.Int).SetInt64(400) @@ -561,15 +510,16 @@ func TestExecuteTransaction(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: sequencerAddress.String(), BatchL2Data: batchL2Data, OldStateRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(time.Now().Unix()), UpdateMerkleTree: 1, ChainId: stateCfg.ChainID, + ForkId: forkID, } log.Debugf("%v", processBatchRequest) @@ -580,7 +530,6 @@ func TestExecuteTransaction(t *testing.T) { // TODO: assert processBatchResponse to make sure that the response makes sense } -/* func TestCheckSupersetBatchTransactions(t *testing.T) { tcs := []struct { description string @@ -654,7 +603,6 @@ func TestCheckSupersetBatchTransactions(t *testing.T) { }) } } -*/ func TestGetTxsHashesByBatchNumber(t *testing.T) { // Init database instance @@ -702,162 +650,6 @@ func TestGetTxsHashesByBatchNumber(t *testing.T) { require.NoError(t, dbTx.Commit(ctx)) } -func TestDetermineProcessedTransactions(t *testing.T) { - tcs := []struct { - description string - input []*state.ProcessTransactionResponse - expectedProcessedOutput []*state.ProcessTransactionResponse - expectedUnprocessedOutput map[string]*state.ProcessTransactionResponse - }{ - { - description: "empty input returns empty", - input: []*state.ProcessTransactionResponse{}, - expectedProcessedOutput: []*state.ProcessTransactionResponse{}, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{}, - }, - { - description: "single processed transaction returns itself", - input: []*state.ProcessTransactionResponse{ - {IsProcessed: true}, - }, - expectedProcessedOutput: []*state.ProcessTransactionResponse{ - {IsProcessed: true}, - }, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{}, - }, - { - description: "single unprocessed transaction returns empty", - input: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: false, - }, - }, - expectedProcessedOutput: []*state.ProcessTransactionResponse{}, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{ - "0x000000000000000000000000000000000000000000000000000000000000000a": { - TxHash: common.HexToHash("a"), - IsProcessed: false, - }, - }, - }, - { - description: "multiple processed transactions", - input: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("b"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("c"), - IsProcessed: true, - }, - }, - expectedProcessedOutput: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("b"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("c"), - IsProcessed: true, - }, - }, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{}, - }, - { - description: "multiple unprocessed transactions", - input: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: false, - }, - { - TxHash: common.HexToHash("b"), - IsProcessed: false, - }, - { - TxHash: common.HexToHash("c"), - IsProcessed: false, - }, - }, - expectedProcessedOutput: []*state.ProcessTransactionResponse{}, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{ - "0x000000000000000000000000000000000000000000000000000000000000000a": { - TxHash: common.HexToHash("a"), - IsProcessed: false, - }, - "0x000000000000000000000000000000000000000000000000000000000000000b": { - TxHash: common.HexToHash("b"), - IsProcessed: false, - }, - "0x000000000000000000000000000000000000000000000000000000000000000c": { - TxHash: common.HexToHash("c"), - IsProcessed: false, - }, - }, - }, - { - description: "mixed processed and unprocessed transactions", - input: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("b"), - IsProcessed: false, - }, - { - TxHash: common.HexToHash("c"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("d"), - IsProcessed: false, - }, - }, - expectedProcessedOutput: []*state.ProcessTransactionResponse{ - { - TxHash: common.HexToHash("a"), - IsProcessed: true, - }, - { - TxHash: common.HexToHash("c"), - IsProcessed: true, - }, - }, - expectedUnprocessedOutput: map[string]*state.ProcessTransactionResponse{ - "0x000000000000000000000000000000000000000000000000000000000000000b": { - TxHash: common.HexToHash("b"), - IsProcessed: false, - }, - "0x000000000000000000000000000000000000000000000000000000000000000d": { - TxHash: common.HexToHash("d"), - IsProcessed: false, - }, - }, - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - actualProcessedTx, _, actualUnprocessedTxs, _ := state.DetermineProcessedTransactions(tc.input) - require.Equal(t, tc.expectedProcessedOutput, actualProcessedTx) - require.Equal(t, tc.expectedUnprocessedOutput, actualUnprocessedTxs) - }) - } -} - func TestGenesis(t *testing.T) { block := state.Block{ BlockNumber: 1, @@ -901,7 +693,7 @@ func TestGenesis(t *testing.T) { } genesis := state.Genesis{ - Actions: actions, + GenesisActions: actions, } initOrResetDB() @@ -936,7 +728,7 @@ func TestGenesis(t *testing.T) { } func TestExecutor(t *testing.T) { - var expectedNewRoot = "0xbff23fc2c168c033aaac77503ce18f958e9689d5cdaebb88c5524ce5c0319de3" + var expectedNewRoot = "0xa2b0ad9cc19e2a4aa9a6d7e14b15e5e951e319ed17b619878bec201b4d064c3e" db := map[string]string{ "2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90": "00000000000000000000000000000000000000000000000000000000000000000d1f0da5a7b620c843fd1e18e59fd724d428d25da0cb1888e31f5542ac227c060000000000000000000000000000000000000000000000000000000000000000", @@ -948,16 +740,17 @@ func TestExecutor(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D").String(), BatchL2Data: common.Hex2Bytes("ee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e880801cee7e01dc62f69a12c3510c6d64de04ee6346d84b6a017f3e786c7d87f963e75d8cc91fa983cd6d9cf55fff80d73bd26cd333b0f098acc1e58edb1fd484ad731b"), OldStateRoot: common.Hex2Bytes("2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90"), GlobalExitRoot: common.Hex2Bytes("090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9"), - OldLocalExitRoot: common.Hex2Bytes("17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e"), + OldAccInputHash: common.Hex2Bytes("17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e"), EthTimestamp: uint64(1944498031), UpdateMerkleTree: 0, Db: db, ChainId: stateCfg.ChainID, + ForkId: forkID, } processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) @@ -975,6 +768,31 @@ func TestExecutorRevert(t *testing.T) { scRevertByteCode, err := testutils.ReadBytecode("Revert2/Revert2.bin") require.NoError(t, err) + // Set Genesis + block := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: sequencerAddress.String(), + Type: int(merkletree.LeafTypeBalance), + Value: "10000000", + }, + }, + } + + initOrResetDB() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + stateRoot, err := testState.SetGenesis(ctx, block, genesis, dbTx) + require.NoError(t, err) + // Deploy revert.sol tx0 := types.NewTx(&types.LegacyTx{ Nonce: 0, @@ -1003,97 +821,160 @@ func TestExecutorRevert(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: sequencerAddress.String(), BatchL2Data: batchL2Data, - OldStateRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldStateRoot: stateRoot, GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(time.Now().Unix()), UpdateMerkleTree: 0, ChainId: stateCfg.ChainID, + ForkId: forkID, } processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) require.NoError(t, err) - assert.NotEqual(t, "", processBatchResponse.Responses[0].Error) -} + assert.Equal(t, runtime.ErrExecutionReverted, executor.RomErr(processBatchResponse.Responses[1].Error)) -func TestExecutorLogs(t *testing.T) { - var chainIDSequencer = new(big.Int).SetInt64(1000) - var sequencerAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") - var sequencerPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" - var sequencerBalance = 4000000 - var scAddress = common.HexToAddress("0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98") - scLogsByteCode, err := testutils.ReadBytecode("EmitLog2/EmitLog2.bin") - require.NoError(t, err) + // Unsigned + receipt := &types.Receipt{ + Type: uint8(signedTx0.Type()), + PostState: processBatchResponse.Responses[0].StateRoot, + CumulativeGasUsed: processBatchResponse.Responses[0].GasUsed, + BlockNumber: big.NewInt(0), + GasUsed: processBatchResponse.Responses[0].GasUsed, + TxHash: signedTx0.Hash(), + TransactionIndex: 0, + Status: types.ReceiptStatusSuccessful, + } - // Genesis DB - genesisDB := map[string]string{ - "2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90": "00000000000000000000000000000000000000000000000000000000000000000d1f0da5a7b620c843fd1e18e59fd724d428d25da0cb1888e31f5542ac227c060000000000000000000000000000000000000000000000000000000000000000", - "e31f5542ac227c06d428d25da0cb188843fd1e18e59fd7240d1f0da5a7b620c8": "ed22ec7734d89ff2b2e639153607b7c542b2bd6ec2788851b7819329410847833e63658ee0db910d0b3e34316e81aa10e0dc203d93f4e3e5e10053d0ebc646020000000000000000000000000000000000000000000000000000000000000000", - "b78193294108478342b2bd6ec2788851b2e639153607b7c5ed22ec7734d89ff2": "16dde42596b907f049015d7e991a152894dd9dadd060910b60b4d5e9af514018b69b044f5e694795f57d81efba5d4445339438195426ad0a3efad1dd58c2259d0000000000000001000000000000000000000000000000000000000000000000", - "3efad1dd58c2259d339438195426ad0af57d81efba5d4445b69b044f5e694795": "00000000dea000000000000035c9adc5000000000000003600000000000000000000000000000000000000000000000000000000000000000000000000000000", - "e10053d0ebc64602e0dc203d93f4e3e50b3e34316e81aa103e63658ee0db910d": "66ee2be0687eea766926f8ca8796c78a4c2f3e938869b82d649e63bfe1247ba4b69b044f5e694795f57d81efba5d4445339438195426ad0a3efad1dd58c2259d0000000000000001000000000000000000000000000000000000000000000000", + receipt1 := &types.Receipt{ + Type: uint8(signedTx1.Type()), + PostState: processBatchResponse.Responses[1].StateRoot, + CumulativeGasUsed: processBatchResponse.Responses[0].GasUsed + processBatchResponse.Responses[1].GasUsed, + BlockNumber: big.NewInt(0), + GasUsed: signedTx1.Gas(), + TxHash: signedTx1.Hash(), + TransactionIndex: 1, + Status: types.ReceiptStatusSuccessful, } - // Deploy Emitlog2.sol - tx0 := types.NewTx(&types.LegacyTx{ - Nonce: 0, - To: nil, - Value: new(big.Int), - Gas: uint64(sequencerBalance), - GasPrice: new(big.Int).SetUint64(0), - Data: common.Hex2Bytes(scLogsByteCode), - }) + header := &types.Header{ + Number: big.NewInt(1), + ParentHash: state.ZeroHash, + Coinbase: state.ZeroAddress, + Root: common.BytesToHash(processBatchResponse.NewStateRoot), + GasUsed: receipt1.GasUsed, + GasLimit: receipt1.GasUsed, + Time: uint64(time.Now().Unix()), + } - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(sequencerPvtKey, "0x")) - require.NoError(t, err) - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainIDSequencer) - require.NoError(t, err) + receipts := []*types.Receipt{receipt, receipt1} - signedTx0, err := auth.Signer(auth.From, tx0) - require.NoError(t, err) + transactions := []*types.Transaction{signedTx0, signedTx1} - // Call SC method - tx1 := types.NewTransaction(1, scAddress, new(big.Int), 40000, new(big.Int).SetUint64(1), common.Hex2Bytes("7966b4f6")) - signedTx1, err := auth.Signer(auth.From, tx1) - require.NoError(t, err) + // Create block to be able to calculate its hash + l2Block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) + l2Block.ReceivedAt = time.Now() - batchL2Data, err := state.EncodeTransactions([]types.Transaction{*signedTx0, *signedTx1}) + receipt.BlockHash = l2Block.Hash() + + err = testState.AddL2Block(ctx, 0, l2Block, receipts, dbTx) + require.NoError(t, err) + l2Block, err = testState.GetL2BlockByHash(ctx, l2Block.Hash(), dbTx) require.NoError(t, err) - // Create Batch - processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, - Coinbase: sequencerAddress.String(), - BatchL2Data: batchL2Data, - OldStateRoot: common.Hex2Bytes("2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90"), - GlobalExitRoot: common.Hex2Bytes("090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9"), - OldLocalExitRoot: common.Hex2Bytes("17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e"), - EthTimestamp: uint64(1944498031), - UpdateMerkleTree: 0, - Db: genesisDB, - ChainId: stateCfg.ChainID, - } + require.NoError(t, dbTx.Commit(ctx)) - processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) - require.NoError(t, err) + lastL2BlockNumber := l2Block.NumberU64() - assert.Equal(t, scAddress, common.HexToAddress(string(processBatchResponse.Responses[0].CreateAddress))) + unsignedTx := types.NewTransaction(2, scAddress, new(big.Int), 40000, new(big.Int).SetUint64(1), common.Hex2Bytes("4abbb40a")) - assert.Equal(t, 0, len(processBatchResponse.Responses[0].Logs)) - assert.Equal(t, 3, len(processBatchResponse.Responses[1].Logs)) - assert.Equal(t, 1, len(processBatchResponse.Responses[1].Logs[0].Topics)) - assert.Equal(t, 2, len(processBatchResponse.Responses[1].Logs[1].Topics)) - assert.Equal(t, 4, len(processBatchResponse.Responses[1].Logs[2].Topics)) + result, err := testState.ProcessUnsignedTransaction(ctx, unsignedTx, auth.From, &lastL2BlockNumber, false, nil) + require.NoError(t, err) + require.NotNil(t, result.Err) + assert.Equal(t, fmt.Errorf("execution reverted: Today is not juernes").Error(), result.Err.Error()) } -func TestExecutorTransfer(t *testing.T) { - var chainID = new(big.Int).SetInt64(1000) - var senderAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") - var senderPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" - var receiverAddress = common.HexToAddress("0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FB") +// +//func TestExecutorLogs(t *testing.T) { +// var chainIDSequencer = new(big.Int).SetInt64(1000) +// var sequencerAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") +// var sequencerPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" +// var sequencerBalance = 4000000 +// var scAddress = common.HexToAddress("0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98") +// scLogsByteCode, err := testutils.ReadBytecode("EmitLog2/EmitLog2.bin") +// require.NoError(t, err) +// +// // Genesis DB +// genesisDB := map[string]string{ +// "2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90": "00000000000000000000000000000000000000000000000000000000000000000d1f0da5a7b620c843fd1e18e59fd724d428d25da0cb1888e31f5542ac227c060000000000000000000000000000000000000000000000000000000000000000", +// "e31f5542ac227c06d428d25da0cb188843fd1e18e59fd7240d1f0da5a7b620c8": "ed22ec7734d89ff2b2e639153607b7c542b2bd6ec2788851b7819329410847833e63658ee0db910d0b3e34316e81aa10e0dc203d93f4e3e5e10053d0ebc646020000000000000000000000000000000000000000000000000000000000000000", +// "b78193294108478342b2bd6ec2788851b2e639153607b7c5ed22ec7734d89ff2": "16dde42596b907f049015d7e991a152894dd9dadd060910b60b4d5e9af514018b69b044f5e694795f57d81efba5d4445339438195426ad0a3efad1dd58c2259d0000000000000001000000000000000000000000000000000000000000000000", +// "3efad1dd58c2259d339438195426ad0af57d81efba5d4445b69b044f5e694795": "00000000dea000000000000035c9adc5000000000000003600000000000000000000000000000000000000000000000000000000000000000000000000000000", +// "e10053d0ebc64602e0dc203d93f4e3e50b3e34316e81aa103e63658ee0db910d": "66ee2be0687eea766926f8ca8796c78a4c2f3e938869b82d649e63bfe1247ba4b69b044f5e694795f57d81efba5d4445339438195426ad0a3efad1dd58c2259d0000000000000001000000000000000000000000000000000000000000000000", +// } +// +// // Deploy Emitlog2.sol +// tx0 := types.NewTx(&types.LegacyTx{ +// Nonce: 0, +// To: nil, +// Value: new(big.Int), +// Gas: uint64(sequencerBalance), +// GasPrice: new(big.Int).SetUint64(0), +// Data: common.Hex2Bytes(scLogsByteCode), +// }) +// +// privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(sequencerPvtKey, "0x")) +// require.NoError(t, err) +// auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainIDSequencer) +// require.NoError(t, err) +// +// signedTx0, err := auth.Signer(auth.From, tx0) +// require.NoError(t, err) +// +// // Call SC method +// tx1 := types.NewTransaction(1, scAddress, new(big.Int), 40000, new(big.Int).SetUint64(1), common.Hex2Bytes("7966b4f6")) +// signedTx1, err := auth.Signer(auth.From, tx1) +// require.NoError(t, err) +// +// batchL2Data, err := state.EncodeTransactions([]types.Transaction{*signedTx0, *signedTx1}) +// require.NoError(t, err) +// +// // Create Batch +// processBatchRequest := &executorclientpb.ProcessBatchRequest{ +// OldBatchNum: 0, +// Coinbase: sequencerAddress.String(), +// BatchL2Data: batchL2Data, +// OldStateRoot: common.Hex2Bytes("2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90"), +// GlobalExitRoot: common.Hex2Bytes("090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9"), +// OldAccInputHash: common.Hex2Bytes("17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e"), +// EthTimestamp: uint64(1944498031), +// UpdateMerkleTree: 0, +// Db: genesisDB, +// ChainId: stateCfg.ChainID, +// ForkId: forkID, +// } +// +// processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) +// require.NoError(t, err) +// +// assert.Equal(t, scAddress, common.HexToAddress(string(processBatchResponse.Responses[0].CreateAddress))) +// +// assert.Equal(t, 0, len(processBatchResponse.Responses[0].Logs)) +// assert.Equal(t, 4, len(processBatchResponse.Responses[1].Logs)) +// assert.Equal(t, 4, len(processBatchResponse.Responses[1].Logs[0].Topics)) +// assert.Equal(t, 2, len(processBatchResponse.Responses[1].Logs[1].Topics)) +// assert.Equal(t, 1, len(processBatchResponse.Responses[1].Logs[2].Topics)) +// assert.Equal(t, 0, len(processBatchResponse.Responses[1].Logs[3].Topics)) +//} + +func TestExecutorTransfer(t *testing.T) { + var chainID = new(big.Int).SetInt64(1000) + var senderAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + var senderPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + var receiverAddress = common.HexToAddress("0xb1D0Dc8E2Ce3a93EB2b32f4C7c3fD9dDAf1211FB") // Set Genesis block := state.Block{ @@ -1104,7 +985,7 @@ func TestExecutorTransfer(t *testing.T) { } genesis := state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", Type: int(merkletree.LeafTypeBalance), @@ -1144,15 +1025,16 @@ func TestExecutorTransfer(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: receiverAddress.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot, GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, ChainId: stateCfg.ChainID, + ForkId: forkID, } // Read Sender Balance before execution @@ -1178,6 +1060,20 @@ func TestExecutorTransfer(t *testing.T) { balance, err = stateTree.GetBalance(ctx, receiverAddress, processBatchResponse.Responses[0].StateRoot) require.NoError(t, err) require.Equal(t, uint64(21002), balance.Uint64()) + + // Read Modified Addresses directly from response + readWriteAddresses := processBatchResponse.ReadWriteAddresses + log.Debug(receiverAddress.String()) + data := readWriteAddresses[strings.ToLower(receiverAddress.String())] + require.Equal(t, "21002", data.Balance) + + // Read Modified Addresses from converted response + converted, err := testState.TestConvertToProcessBatchResponse([]types.Transaction{*signedTx}, processBatchResponse) + require.NoError(t, err) + convertedData := converted.ReadWriteAddresses[receiverAddress] + require.Equal(t, uint64(21002), convertedData.Balance.Uint64()) + require.Equal(t, receiverAddress, convertedData.Address) + require.Equal(t, (*uint64)(nil), convertedData.Nonce) } func TestExecutorTxHashAndRLP(t *testing.T) { @@ -1198,18 +1094,29 @@ func TestExecutorTxHashAndRLP(t *testing.T) { Link string `json:"link"` } - var testCases []TxHashTestCase + var testCases, testCases2 []TxHashTestCase jsonFile, err := os.Open(filepath.Clean("test/vectors/src/tx-hash-ethereum/uniswap_formated.json")) require.NoError(t, err) defer func() { _ = jsonFile.Close() }() - bytes, err := ioutil.ReadAll(jsonFile) + bytes, err := io.ReadAll(jsonFile) require.NoError(t, err) err = json.Unmarshal(bytes, &testCases) require.NoError(t, err) + jsonFile2, err := os.Open(filepath.Clean("test/vectors/src/tx-hash-ethereum/rlp.json")) + require.NoError(t, err) + defer func() { _ = jsonFile2.Close() }() + + bytes2, err := io.ReadAll(jsonFile2) + require.NoError(t, err) + + err = json.Unmarshal(bytes2, &testCases2) + require.NoError(t, err) + testCases = append(testCases, testCases2...) + for x, testCase := range testCases { var stateRoot = state.ZeroHash var receiverAddress = common.HexToAddress(testCase.To) @@ -1255,6 +1162,8 @@ func TestExecutorTxHashAndRLP(t *testing.T) { R: r, S: s, }) + t.Log("chainID: ", tx.ChainId()) + t.Log("txHash: ", tx.Hash()) require.Equal(t, testCase.Hash, tx.Hash().String()) @@ -1263,15 +1172,16 @@ func TestExecutorTxHashAndRLP(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: uint64(x + 1), + OldBatchNum: uint64(x), Coinbase: receiverAddress.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot.Bytes(), GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, ChainId: stateCfg.ChainID, + ForkId: forkID, } // Process batch @@ -1336,7 +1246,7 @@ func TestExecutorInvalidNonce(t *testing.T) { ReceivedAt: time.Now(), } genesis := state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: senderAddress.String(), Type: int(merkletree.LeafTypeBalance), @@ -1371,15 +1281,16 @@ func TestExecutorInvalidNonce(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: receiverAddress.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot, GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, ChainId: stateCfg.ChainID, + ForkId: forkID, } // Process batch @@ -1387,7 +1298,7 @@ func TestExecutorInvalidNonce(t *testing.T) { require.NoError(t, err) transactionResponses := processBatchResponse.GetResponses() - assert.Equal(t, executorclientpb.Error_ERROR_INTRINSIC_INVALID_TX, transactionResponses[0].Error, "invalid tx Error, it is expected to be INVALID TX") + assert.Equal(t, true, executor.IsIntrinsicError(transactionResponses[0].Error), "invalid tx Error, it is expected to be INVALID TX") }) } } @@ -1402,7 +1313,7 @@ func TestGenesisNewLeafType(t *testing.T) { } genesis := state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", Type: int(merkletree.LeafTypeBalance), @@ -1537,7 +1448,7 @@ func TestGenesisNewLeafType(t *testing.T) { // storage[address][storageKey] = storageValue // // Currently the test vector includes storage values in base10 format, -// // our SetGenesis requires base16 values. +// // our SetGenesisAccountsBalance requires base16 values. // item.Value = hex.EncodeBig(storageValue) // } // } @@ -1557,7 +1468,7 @@ func TestGenesisNewLeafType(t *testing.T) { // dbTx, err := testState.BeginStateTransaction(ctx) // require.NoError(t, err) -// stateRoot, err := testState.SetGenesis(ctx, block, genesis, dbTx) +// stateRoot, err := testState.SetGenesisAccountsBalance(ctx, block, genesis, dbTx) // require.NoError(t, err) // require.NoError(t, dbTx.Commit(ctx)) @@ -1599,7 +1510,7 @@ func TestGenesisNewLeafType(t *testing.T) { // BatchNumber: tv.Traces.NumBatch, // Coinbase: common.HexToAddress(tv.Traces.SequencerAddr), // Timestamp: time.Unix(int64(tv.Traces.Timestamp), 0), -// GlobalExitRoot: common.HexToHash(tv.GlobalExitRoot), +// globalExitRoot: common.HexToHash(tv.globalExitRoot), // } // if strings.HasPrefix(tv.BatchL2Data, "0x") { // nolint @@ -1678,7 +1589,7 @@ func TestExecutorUnsignedTransactions(t *testing.T) { dbTx, err := testState.BeginStateTransaction(context.Background()) require.NoError(t, err) // Set genesis - genesis := state.Genesis{Actions: []*state.GenesisAction{ + genesis := state.Genesis{GenesisActions: []*state.GenesisAction{ { Address: sequencerAddress.Hex(), Type: int(merkletree.LeafTypeBalance), @@ -1699,17 +1610,21 @@ func TestExecutorUnsignedTransactions(t *testing.T) { *signedTxFirstIncrement, *signedTxFirstRetrieve, } - processBatchResponse, err := testState.ProcessSequencerBatch(context.Background(), 1, signedTxs, dbTx) + + batchL2Data, err := state.EncodeTransactions(signedTxs) + require.NoError(t, err) + + processBatchResponse, err := testState.ProcessSequencerBatch(context.Background(), 1, batchL2Data, metrics.SequencerCallerLabel, dbTx) require.NoError(t, err) // assert signed tx do deploy sc - assert.Nil(t, processBatchResponse.Responses[0].Error) + assert.Nil(t, processBatchResponse.Responses[0].RomError) assert.Equal(t, scAddress, processBatchResponse.Responses[0].CreateAddress) // assert signed tx to increment counter - assert.Nil(t, processBatchResponse.Responses[1].Error) + assert.Nil(t, processBatchResponse.Responses[1].RomError) // assert signed tx to increment counter - assert.Nil(t, processBatchResponse.Responses[2].Error) + assert.Nil(t, processBatchResponse.Responses[2].RomError) assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000001", hex.EncodeToString(processBatchResponse.Responses[2].ReturnValue)) // Add txs to DB @@ -1736,7 +1651,9 @@ func TestExecutorUnsignedTransactions(t *testing.T) { Data: retrieveFnSignature, }) l2BlockNumber := uint64(3) - result := testState.ProcessUnsignedTransaction(context.Background(), unsignedTxSecondRetrieve, common.HexToAddress("0x1000000000000000000000000000000000000000"), &l2BlockNumber, true, nil) + + result, err := testState.ProcessUnsignedTransaction(context.Background(), unsignedTxSecondRetrieve, common.HexToAddress("0x1000000000000000000000000000000000000000"), &l2BlockNumber, true, nil) + require.NoError(t, err) // assert unsigned tx assert.Nil(t, result.Err) assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000001", hex.EncodeToString(result.ReturnValue)) @@ -1799,7 +1716,7 @@ func TestAddGetL2Block(t *testing.T) { // Create block to be able to calculate its hash l2Block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) - block.ReceivedAt = time + l2Block.ReceivedAt = time receipt.BlockHash = l2Block.Hash() @@ -1814,6 +1731,8 @@ func TestAddGetL2Block(t *testing.T) { require.NoError(t, err) assert.Equal(t, l2Block.Hash(), result.Hash()) + assert.Equal(t, l2Block.ReceivedAt.Unix(), result.ReceivedAt.Unix()) + assert.Equal(t, l2Block.Time(), result.Time()) require.NoError(t, dbTx.Commit(ctx)) } @@ -1832,10 +1751,10 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { require.NoError(t, err) defer func() { _ = jsonFile.Close() }() - bytes, err := ioutil.ReadAll(jsonFile) + Bytes, err := ioutil.ReadAll(jsonFile) require.NoError(t, err) - err = json.Unmarshal(bytes, &testCases) + err = json.Unmarshal(Bytes, &testCases) require.NoError(t, err) // Set Genesis @@ -1865,7 +1784,7 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { dbTx, err := testState.BeginStateTransaction(ctx) require.NoError(t, err) - stateRoot, err := testState.SetGenesis(ctx, block, genesis, dbTx) + stateRoot, err := testState.SetGenesisAccountsBalance(ctx, block, genesis, dbTx) require.NoError(t, err) require.NoError(t, dbTx.Commit(ctx)) @@ -1893,7 +1812,7 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { Coinbase: common.Address{}.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot, - GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + globalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, @@ -1905,10 +1824,10 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { require.NoError(t, err) defer func() { _ = jsonFile.Close() }() - bytes, err := ioutil.ReadAll(jsonFile) + Bytes, err := ioutil.ReadAll(jsonFile) require.NoError(t, err) - err = json.Unmarshal(bytes, &testCases) + err = json.Unmarshal(Bytes, &testCases) require.NoError(t, err) // Set Genesis @@ -1938,7 +1857,7 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { dbTx, err := testState.BeginStateTransaction(ctx) require.NoError(t, err) - stateRoot, err := testState.SetGenesis(ctx, block, genesis, dbTx) + stateRoot, err := testState.SetGenesisAccountsBalance(ctx, block, genesis, dbTx) require.NoError(t, err) require.NoError(t, dbTx.Commit(ctx)) @@ -1966,11 +1885,12 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { Coinbase: common.Address{}.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot, - GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + globalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, ChainId: stateCfg.ChainID, + ForkId: forkID, } // Process batch @@ -1992,7 +1912,7 @@ func TestExecutorUniswapOutOfCounters(t *testing.T) { Coinbase: common.Address{}.String(), BatchL2Data: batchL2Data, OldStateRoot: processBatchResponse.NewStateRoot, - GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + globalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(0), UpdateMerkleTree: 1, @@ -2040,7 +1960,7 @@ func TestExecutorEstimateGas(t *testing.T) { } genesis := state.Genesis{ - Actions: []*state.GenesisAction{ + GenesisActions: []*state.GenesisAction{ { Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", Type: int(merkletree.LeafTypeBalance), @@ -2098,22 +2018,23 @@ func TestExecutorEstimateGas(t *testing.T) { // Create Batch processBatchRequest := &executorclientpb.ProcessBatchRequest{ - BatchNum: 1, + OldBatchNum: 0, Coinbase: sequencerAddress.String(), BatchL2Data: batchL2Data, OldStateRoot: stateRoot, GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), - OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), EthTimestamp: uint64(time.Now().Unix()), UpdateMerkleTree: 0, ChainId: stateCfg.ChainID, + ForkId: forkID, } processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) require.NoError(t, err) assert.NotEqual(t, "", processBatchResponse.Responses[0].Error) - convertedResponse, err := state.TestConvertToProcessBatchResponse([]types.Transaction{*signedTx0, *signedTx1}, processBatchResponse) + convertedResponse, err := testState.TestConvertToProcessBatchResponse([]types.Transaction{*signedTx0, *signedTx1}, processBatchResponse) require.NoError(t, err) log.Debugf("%v", len(convertedResponse.Responses)) @@ -2122,7 +2043,7 @@ func TestExecutorEstimateGas(t *testing.T) { require.NoError(t, err) processingContext := state.ProcessingContext{ - BatchNumber: processBatchRequest.BatchNum, + BatchNumber: processBatchRequest.OldBatchNum + 1, Coinbase: common.Address{}, Timestamp: time.Now(), GlobalExitRoot: common.BytesToHash(processBatchRequest.GlobalExitRoot), @@ -2131,11 +2052,11 @@ func TestExecutorEstimateGas(t *testing.T) { err = testState.OpenBatch(ctx, processingContext, dbTx) require.NoError(t, err) - err = testState.StoreTransactions(ctx, processBatchRequest.BatchNum, convertedResponse.Responses, dbTx) + err = testState.StoreTransactions(ctx, processBatchRequest.OldBatchNum+1, convertedResponse.Responses, dbTx) require.NoError(t, err) processingReceipt := state.ProcessingReceipt{ - BatchNumber: processBatchRequest.BatchNum, + BatchNumber: processBatchRequest.OldBatchNum + 1, StateRoot: convertedResponse.NewStateRoot, LocalExitRoot: convertedResponse.NewLocalExitRoot, } @@ -2157,7 +2078,10 @@ func TestExecutorEstimateGas(t *testing.T) { signedTx2, err := auth.Signer(auth.From, tx2) require.NoError(t, err) - estimatedGas, err := testState.EstimateGas(signedTx2, sequencerAddress, nil, nil) + blockNumber, err := testState.GetLastL2BlockNumber(ctx, nil) + require.NoError(t, err) + + estimatedGas, _, err := testState.EstimateGas(signedTx2, sequencerAddress, &blockNumber, nil) require.NoError(t, err) log.Debugf("Estimated gas = %v", estimatedGas) @@ -2165,6 +2089,633 @@ func TestExecutorEstimateGas(t *testing.T) { tx3 := types.NewTransaction(nonce, scAddress, new(big.Int), 40000, new(big.Int).SetUint64(1), common.Hex2Bytes("4abbb40a")) signedTx3, err := auth.Signer(auth.From, tx3) require.NoError(t, err) - _, err = testState.EstimateGas(signedTx3, sequencerAddress, nil, nil) + _, _, err = testState.EstimateGas(signedTx3, sequencerAddress, &blockNumber, nil) require.Error(t, err) } + +// TODO: Uncomment once the executor properly returns gas refund +/* +func TestExecutorGasRefund(t *testing.T) { + var chainIDSequencer = new(big.Int).SetInt64(1000) + var sequencerAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + var sequencerPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + var scAddress = common.HexToAddress("0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98") + var sequencerBalance = 4000000 + scStorageByteCode, err := testutils.ReadBytecode("Storage/Storage.bin") + require.NoError(t, err) + + // Set Genesis + block := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + + genesis := state.Genesis{ + Actions: []*state.GenesisAction{ + { + Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + { + Address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + { + Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + }, + } + + initOrResetDB() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + stateRoot, err := testState.SetGenesisAccountsBalance(ctx, block, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + // Deploy contract + tx0 := types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: nil, + Value: new(big.Int), + Gas: uint64(sequencerBalance), + GasPrice: new(big.Int).SetUint64(0), + Data: common.Hex2Bytes(scStorageByteCode), + }) + + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(sequencerPvtKey, "0x")) + require.NoError(t, err) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainIDSequencer) + require.NoError(t, err) + + signedTx0, err := auth.Signer(auth.From, tx0) + require.NoError(t, err) + + // Call SC method to set value to 123456 + tx1 := types.NewTransaction(1, scAddress, new(big.Int), 80000, new(big.Int).SetUint64(0), common.Hex2Bytes("6057361d000000000000000000000000000000000000000000000000000000000001e240")) + signedTx1, err := auth.Signer(auth.From, tx1) + require.NoError(t, err) + + batchL2Data, err := state.EncodeTransactions([]types.Transaction{*signedTx0, *signedTx1}) + require.NoError(t, err) + + // Create Batch + processBatchRequest := &executorclientpb.ProcessBatchRequest{ + BatchNum: 1, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data, + OldStateRoot: stateRoot, + globalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 1, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + assert.Equal(t, pb.Error_ERROR_NO_ERROR, processBatchResponse.Responses[0].Error) + assert.Equal(t, pb.Error_ERROR_NO_ERROR, processBatchResponse.Responses[1].Error) + + // Preparation to be able to estimate gas + convertedResponse, err := state.TestConvertToProcessBatchResponse([]types.Transaction{*signedTx0, *signedTx1}, processBatchResponse) + require.NoError(t, err) + log.Debugf("%v", len(convertedResponse.Responses)) + + // Store processed txs into the batch + dbTx, err = testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + processingContext := state.ProcessingContext{ + BatchNumber: processBatchRequest.BatchNum, + Coinbase: common.Address{}, + Timestamp: time.Now(), + globalExitRoot: common.BytesToHash(processBatchRequest.globalExitRoot), + } + + err = testState.OpenBatch(ctx, processingContext, dbTx) + require.NoError(t, err) + + err = testState.StoreTransactions(ctx, processBatchRequest.BatchNum, convertedResponse.Responses, dbTx) + require.NoError(t, err) + + processingReceipt := state.ProcessingReceipt{ + BatchNumber: processBatchRequest.BatchNum, + StateRoot: convertedResponse.NewStateRoot, + LocalExitRoot: convertedResponse.NewLocalExitRoot, + } + + err = testState.CloseBatch(ctx, processingReceipt, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + // Retrieve Value + tx2 := types.NewTransaction(2, scAddress, new(big.Int), 80000, new(big.Int).SetUint64(0), common.Hex2Bytes("2e64cec1")) + signedTx2, err := auth.Signer(auth.From, tx2) + require.NoError(t, err) + + estimatedGas, _, err := testState.EstimateGas(signedTx2, sequencerAddress, nil, nil) + require.NoError(t, err) + log.Debugf("Estimated gas = %v", estimatedGas) + + tx2 = types.NewTransaction(2, scAddress, new(big.Int), estimatedGas, new(big.Int).SetUint64(0), common.Hex2Bytes("2e64cec1")) + signedTx2, err = auth.Signer(auth.From, tx2) + require.NoError(t, err) + + batchL2Data, err = state.EncodeTransactions([]types.Transaction{*signedTx2}) + require.NoError(t, err) + + processBatchRequest = &executorclientpb.ProcessBatchRequest{ + BatchNum: 2, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data, + OldStateRoot: processBatchResponse.NewStateRoot, + globalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldLocalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 1, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err = executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + assert.Equal(t, pb.Error_ERROR_NO_ERROR, processBatchResponse.Responses[0].Error) + assert.LessOrEqual(t, processBatchResponse.Responses[0].GasUsed, estimatedGas) + assert.NotEqual(t, uint64(0), processBatchResponse.Responses[0].GasRefunded) + assert.Equal(t, new(big.Int).SetInt64(123456), new(big.Int).SetBytes(processBatchResponse.Responses[0].ReturnValue)) +} +*/ + +func TestExecutorGasEstimationMultisig(t *testing.T) { + var chainIDSequencer = new(big.Int).SetInt64(1000) + var sequencerAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + var sequencerPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + var erc20SCAddress = common.HexToAddress("0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98") + var multisigSCAddress = common.HexToAddress("0x85e844b762a271022b692cf99ce5c59ba0650ac8") + var multisigParameter = "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000617b3a3528F9cDd6630fd3301B9c8911F7Bf063D000000000000000000000000B2D0a21D2b14679331f67F3FAB36366ef2270312000000000000000000000000B2bF7Ef15AFfcd23d99A9FB41a310992a70Ed7720000000000000000000000005b6C62FF5dC5De57e9B1a36B64BE3ef4Ac9b08fb" + var sequencerBalance = 4000000 + scERC20ByteCode, err := testutils.ReadBytecode("../compiled/ERC20Token/ERC20Token.bin") + require.NoError(t, err) + scMultiSigByteCode, err := testutils.ReadBytecode("../compiled/MultiSigWallet/MultiSigWallet.bin") + require.NoError(t, err) + + // Set Genesis + block := state.Block{ + BlockNumber: 0, + BlockHash: state.ZeroHash, + ParentHash: state.ZeroHash, + ReceivedAt: time.Now(), + } + + genesis := state.Genesis{ + GenesisActions: []*state.GenesisAction{ + { + Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + { + Address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + { + Address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + }, + } + + initOrResetDB() + + dbTx, err := testState.BeginStateTransaction(ctx) + require.NoError(t, err) + stateRoot, err := testState.SetGenesis(ctx, block, genesis, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + // Deploy contract + tx0 := types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: nil, + Value: new(big.Int), + Gas: uint64(sequencerBalance), + GasPrice: new(big.Int).SetUint64(0), + Data: common.Hex2Bytes(scERC20ByteCode), + }) + + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(sequencerPvtKey, "0x")) + require.NoError(t, err) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainIDSequencer) + require.NoError(t, err) + + signedTx0, err := auth.Signer(auth.From, tx0) + require.NoError(t, err) + + // Deploy contract + tx1 := types.NewTx(&types.LegacyTx{ + Nonce: 1, + To: nil, + Value: new(big.Int), + Gas: uint64(sequencerBalance), + GasPrice: new(big.Int).SetUint64(0), + Data: common.Hex2Bytes(scMultiSigByteCode + multisigParameter), + }) + + signedTx1, err := auth.Signer(auth.From, tx1) + require.NoError(t, err) + + // Transfer Ownership + tx2 := types.NewTransaction(2, erc20SCAddress, new(big.Int), 80000, new(big.Int).SetUint64(0), common.Hex2Bytes("f2fde38b00000000000000000000000085e844b762a271022b692cf99ce5c59ba0650ac8")) + signedTx2, err := auth.Signer(auth.From, tx2) + require.NoError(t, err) + + // Transfer balance to multisig smart contract + tx3 := types.NewTx(&types.LegacyTx{ + Nonce: 3, + To: &multisigSCAddress, + Value: new(big.Int).SetUint64(1000000000), + Gas: uint64(30000), + GasPrice: new(big.Int).SetUint64(1), + Data: nil, + }) + signedTx3, err := auth.Signer(auth.From, tx3) + require.NoError(t, err) + + // Submit Transaction + tx4 := types.NewTransaction(4, multisigSCAddress, new(big.Int), 150000, new(big.Int).SetUint64(0), common.Hex2Bytes("c64274740000000000000000000000001275fbb540c8efc58b812ba83b0d0b8b9917ae98000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014352ca32838ab928d9e55bd7d1a39cb7fbd453ab1000000000000000000000000")) + signedTx4, err := auth.Signer(auth.From, tx4) + require.NoError(t, err) + + // Confirm transaction + tx5 := types.NewTransaction(5, multisigSCAddress, new(big.Int), 150000, new(big.Int).SetUint64(0), common.Hex2Bytes("c01a8c840000000000000000000000000000000000000000000000000000000000000000")) + signedTx5, err := auth.Signer(auth.From, tx5) + require.NoError(t, err) + + transactions := []types.Transaction{*signedTx0, *signedTx1, *signedTx2, *signedTx3, *signedTx4, *signedTx5} + + batchL2Data, err := state.EncodeTransactions(transactions) + require.NoError(t, err) + + // Create Batch + processBatchRequest := &executorclientpb.ProcessBatchRequest{ + OldBatchNum: 0, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data, + OldStateRoot: stateRoot, + GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 1, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[0].Error) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[1].Error) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[2].Error) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[3].Error) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[4].Error) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[5].Error) + + // Check SC code + // Check Smart Contracts Code + code, err := stateTree.GetCode(ctx, erc20SCAddress, processBatchResponse.NewStateRoot) + require.NoError(t, err) + require.NotEmpty(t, code) + code, err = stateTree.GetCode(ctx, multisigSCAddress, processBatchResponse.NewStateRoot) + require.NoError(t, err) + require.NotEmpty(t, code) + + // Check Smart Contract Balance + balance, err := stateTree.GetBalance(ctx, multisigSCAddress, processBatchResponse.NewStateRoot) + require.NoError(t, err) + require.Equal(t, uint64(1000000000), balance.Uint64()) + + // Preparation to be able to estimate gas + convertedResponse, err := testState.TestConvertToProcessBatchResponse(transactions, processBatchResponse) + require.NoError(t, err) + log.Debugf("%v", len(convertedResponse.Responses)) + + // Store processed txs into the batch + dbTx, err = testState.BeginStateTransaction(ctx) + require.NoError(t, err) + + processingContext := state.ProcessingContext{ + BatchNumber: processBatchRequest.OldBatchNum + 1, + Coinbase: common.Address{}, + Timestamp: time.Now(), + GlobalExitRoot: common.BytesToHash(processBatchRequest.GlobalExitRoot), + } + + err = testState.OpenBatch(ctx, processingContext, dbTx) + require.NoError(t, err) + + err = testState.StoreTransactions(ctx, processBatchRequest.OldBatchNum+1, convertedResponse.Responses, dbTx) + require.NoError(t, err) + + processingReceipt := state.ProcessingReceipt{ + BatchNumber: processBatchRequest.OldBatchNum + 1, + StateRoot: convertedResponse.NewStateRoot, + LocalExitRoot: convertedResponse.NewLocalExitRoot, + } + + err = testState.CloseBatch(ctx, processingReceipt, dbTx) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(ctx)) + + // Revoke Confirmation + tx6 := types.NewTransaction(6, multisigSCAddress, new(big.Int), 50000, new(big.Int).SetUint64(0), common.Hex2Bytes("20ea8d860000000000000000000000000000000000000000000000000000000000000000")) + signedTx6, err := auth.Signer(auth.From, tx6) + require.NoError(t, err) + + blockNumber, err := testState.GetLastL2BlockNumber(ctx, nil) + require.NoError(t, err) + + estimatedGas, _, err := testState.EstimateGas(signedTx6, sequencerAddress, &blockNumber, nil) + require.NoError(t, err) + log.Debugf("Estimated gas = %v", estimatedGas) + + tx6 = types.NewTransaction(6, multisigSCAddress, new(big.Int), estimatedGas, new(big.Int).SetUint64(0), common.Hex2Bytes("20ea8d860000000000000000000000000000000000000000000000000000000000000000")) + signedTx6, err = auth.Signer(auth.From, tx6) + require.NoError(t, err) + + batchL2Data, err = state.EncodeTransactions([]types.Transaction{*signedTx6}) + require.NoError(t, err) + + processBatchRequest = &executorclientpb.ProcessBatchRequest{ + OldBatchNum: 1, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data, + OldStateRoot: processBatchResponse.NewStateRoot, + GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 1, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err = executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + assert.Equal(t, executorclientpb.RomError_ROM_ERROR_NO_ERROR, processBatchResponse.Responses[0].Error) + log.Debugf("Used gas = %v", processBatchResponse.Responses[0].GasUsed) +} + +func TestExecuteWithoutUpdatingMT(t *testing.T) { + // Init database instance + initOrResetDB() + + var chainIDSequencer = new(big.Int).SetUint64(stateCfg.ChainID) + var sequencerAddress = common.HexToAddress("0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D") + var sequencerPvtKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + var gasLimit = uint64(4000000) + var scAddress = common.HexToAddress("0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98") + scByteCode, err := testutils.ReadBytecode("Counter/Counter.bin") + require.NoError(t, err) + + // auth + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(sequencerPvtKey, "0x")) + require.NoError(t, err) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainIDSequencer) + require.NoError(t, err) + + // signed tx to deploy SC + unsignedTxDeploy := types.NewTx(&types.LegacyTx{ + Nonce: 0, + To: nil, + Value: new(big.Int), + Gas: gasLimit, + GasPrice: new(big.Int), + Data: common.Hex2Bytes(scByteCode), + }) + signedTxDeploy, err := auth.Signer(auth.From, unsignedTxDeploy) + require.NoError(t, err) + + signedTxs := []types.Transaction{ + *signedTxDeploy, + } + + batchL2Data, err := state.EncodeTransactions(signedTxs) + require.NoError(t, err) + + // Create Batch + processBatchRequest := &executorclientpb.ProcessBatchRequest{ + OldBatchNum: 0, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data, + OldStateRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 0, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err := executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + + // assert signed tx do deploy sc + assert.Equal(t, executorclientpb.RomError(1), processBatchResponse.Responses[0].Error) + assert.Equal(t, scAddress, common.HexToAddress(processBatchResponse.Responses[0].CreateAddress)) + + log.Debug(processBatchResponse) + + incrementFnSignature := crypto.Keccak256Hash([]byte("increment()")).Bytes()[:4] + retrieveFnSignature := crypto.Keccak256Hash([]byte("getCount()")).Bytes()[:4] + + // signed tx to call SC + unsignedTxFirstIncrement := types.NewTx(&types.LegacyTx{ + Nonce: 1, + To: &scAddress, + Value: new(big.Int), + Gas: gasLimit, + GasPrice: new(big.Int), + Data: incrementFnSignature, + }) + + signedTxFirstIncrement, err := auth.Signer(auth.From, unsignedTxFirstIncrement) + require.NoError(t, err) + + unsignedTxFirstRetrieve := types.NewTx(&types.LegacyTx{ + Nonce: 2, + To: &scAddress, + Value: new(big.Int), + Gas: gasLimit, + GasPrice: new(big.Int), + Data: retrieveFnSignature, + }) + + signedTxFirstRetrieve, err := auth.Signer(auth.From, unsignedTxFirstRetrieve) + require.NoError(t, err) + + signedTxs2 := []types.Transaction{ + *signedTxFirstIncrement, + *signedTxFirstRetrieve, + } + + batchL2Data2, err := state.EncodeTransactions(signedTxs2) + require.NoError(t, err) + + // Create Batch 2 + processBatchRequest = &executorclientpb.ProcessBatchRequest{ + OldBatchNum: 1, + Coinbase: sequencerAddress.String(), + BatchL2Data: batchL2Data2, + OldStateRoot: processBatchResponse.NewStateRoot, + GlobalExitRoot: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + OldAccInputHash: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + EthTimestamp: uint64(time.Now().Unix()), + UpdateMerkleTree: 0, + ChainId: stateCfg.ChainID, + ForkId: forkID, + } + + processBatchResponse, err = executorClient.ProcessBatch(ctx, processBatchRequest) + require.NoError(t, err) + + log.Debug(processBatchResponse) + + // assert signed tx to increment counter + assert.Equal(t, executorclientpb.RomError(1), processBatchResponse.Responses[0].Error) + + // assert signed tx to increment counter + assert.Equal(t, executorclientpb.RomError(1), processBatchResponse.Responses[1].Error) + assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000001", hex.EncodeToString(processBatchResponse.Responses[1].ReturnValue)) +} + +func TestExecutorUnsignedTransactionsWithCorrectL2BlockStateRoot(t *testing.T) { + // Init database instance + initOrResetDB() + + // auth + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(operations.DefaultSequencerPrivateKey, "0x")) + require.NoError(t, err) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, new(big.Int).SetUint64(stateCfg.ChainID)) + require.NoError(t, err) + + auth.Nonce = big.NewInt(0) + auth.Value = nil + auth.GasPrice = big.NewInt(0) + auth.GasLimit = uint64(4000000) + auth.NoSend = true + + _, scTx, sc, err := Counter.DeployCounter(auth, ðclient.Client{}) + require.NoError(t, err) + + auth.Nonce = big.NewInt(1) + tx1, err := sc.Increment(auth) + require.NoError(t, err) + + auth.Nonce = big.NewInt(2) + tx2, err := sc.Increment(auth) + require.NoError(t, err) + + auth.Nonce = big.NewInt(3) + tx3, err := sc.Increment(auth) + require.NoError(t, err) + + dbTx, err := testState.BeginStateTransaction(context.Background()) + require.NoError(t, err) + // Set genesis + genesis := state.Genesis{GenesisActions: []*state.GenesisAction{ + { + Address: operations.DefaultSequencerAddress, + Type: int(merkletree.LeafTypeBalance), + Value: "100000000000000000000000", + }, + }} + _, err = testState.SetGenesis(ctx, state.Block{}, genesis, dbTx) + require.NoError(t, err) + batchCtx := state.ProcessingContext{ + BatchNumber: 1, + Coinbase: common.HexToAddress(operations.DefaultSequencerAddress), + Timestamp: time.Now(), + } + err = testState.OpenBatch(context.Background(), batchCtx, dbTx) + require.NoError(t, err) + signedTxs := []types.Transaction{ + *scTx, + *tx1, + *tx2, + *tx3, + } + + batchL2Data, err := state.EncodeTransactions(signedTxs) + require.NoError(t, err) + + processBatchResponse, err := testState.ProcessSequencerBatch(context.Background(), 1, batchL2Data, metrics.SequencerCallerLabel, dbTx) + require.NoError(t, err) + // assert signed tx do deploy sc + assert.Nil(t, processBatchResponse.Responses[0].RomError) + assert.NotEqual(t, state.ZeroAddress, processBatchResponse.Responses[0].CreateAddress.Hex()) + assert.Equal(t, tx1.To().Hex(), processBatchResponse.Responses[0].CreateAddress.Hex()) + + // assert signed tx to increment counter + assert.Nil(t, processBatchResponse.Responses[1].RomError) + assert.Nil(t, processBatchResponse.Responses[2].RomError) + assert.Nil(t, processBatchResponse.Responses[3].RomError) + + // Add txs to DB + err = testState.StoreTransactions(context.Background(), 1, processBatchResponse.Responses, dbTx) + require.NoError(t, err) + // Close batch + err = testState.CloseBatch( + context.Background(), + state.ProcessingReceipt{ + BatchNumber: 1, + StateRoot: processBatchResponse.NewStateRoot, + LocalExitRoot: processBatchResponse.NewLocalExitRoot, + }, dbTx, + ) + require.NoError(t, err) + require.NoError(t, dbTx.Commit(context.Background())) + + getCountFnSignature := crypto.Keccak256Hash([]byte("getCount()")).Bytes()[:4] + getCountUnsignedTx := types.NewTx(&types.LegacyTx{ + To: &processBatchResponse.Responses[0].CreateAddress, + Gas: uint64(100000), + Data: getCountFnSignature, + }) + + l2BlockNumber := uint64(1) + result, err := testState.ProcessUnsignedTransaction(context.Background(), getCountUnsignedTx, auth.From, &l2BlockNumber, true, nil) + require.NoError(t, err) + // assert unsigned tx + assert.Nil(t, result.Err) + assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(result.ReturnValue)) + + l2BlockNumber = uint64(2) + result, err = testState.ProcessUnsignedTransaction(context.Background(), getCountUnsignedTx, auth.From, &l2BlockNumber, true, nil) + require.NoError(t, err) + // assert unsigned tx + assert.Nil(t, result.Err) + assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000001", hex.EncodeToString(result.ReturnValue)) + + l2BlockNumber = uint64(3) + result, err = testState.ProcessUnsignedTransaction(context.Background(), getCountUnsignedTx, auth.From, &l2BlockNumber, true, nil) + require.NoError(t, err) + // assert unsigned tx + assert.Nil(t, result.Err) + assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000002", hex.EncodeToString(result.ReturnValue)) + + l2BlockNumber = uint64(4) + result, err = testState.ProcessUnsignedTransaction(context.Background(), getCountUnsignedTx, auth.From, &l2BlockNumber, true, nil) + require.NoError(t, err) + // assert unsigned tx + assert.Nil(t, result.Err) + assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000003", hex.EncodeToString(result.ReturnValue)) +} diff --git a/state/transaction.go b/state/transaction.go index b2fe99e562..d356c72700 100644 --- a/state/transaction.go +++ b/state/transaction.go @@ -1,8 +1,37 @@ package state import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "strconv" + "strings" + "time" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state/runtime" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/fakevm" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/js" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation/tracers/native" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" + "github.com/holiman/uint256" + "github.com/jackc/pgx/v4" +) + +const ( + two uint = 2 ) // GetSender gets the sender from the transaction's signature @@ -14,3 +43,1049 @@ func GetSender(tx types.Transaction) (common.Address, error) { } return sender, nil } + +// RlpFieldsToLegacyTx parses the rlp fields slice into a type.LegacyTx +// in this specific order: +// +// required fields: +// [0] Nonce uint64 +// [1] GasPrice *big.Int +// [2] Gas uint64 +// [3] To *common.Address +// [4] Value *big.Int +// [5] Data []byte +// +// optional fields: +// [6] V *big.Int +// [7] R *big.Int +// [8] S *big.Int +func RlpFieldsToLegacyTx(fields [][]byte, v, r, s []byte) (tx *types.LegacyTx, err error) { + const ( + fieldsSizeWithoutChainID = 6 + fieldsSizeWithChainID = 7 + ) + + if len(fields) < fieldsSizeWithoutChainID { + return nil, types.ErrTxTypeNotSupported + } + + nonce := big.NewInt(0).SetBytes(fields[0]).Uint64() + gasPrice := big.NewInt(0).SetBytes(fields[1]) + gas := big.NewInt(0).SetBytes(fields[2]).Uint64() + var to *common.Address + + if fields[3] != nil && len(fields[3]) != 0 { + tmp := common.BytesToAddress(fields[3]) + to = &tmp + } + value := big.NewInt(0).SetBytes(fields[4]) + data := fields[5] + + txV := big.NewInt(0).SetBytes(v) + if len(fields) >= fieldsSizeWithChainID { + chainID := big.NewInt(0).SetBytes(fields[6]) + + // a = chainId * 2 + // b = v - 27 + // c = a + 35 + // v = b + c + // + // same as: + // v = v-27+chainId*2+35 + a := new(big.Int).Mul(chainID, big.NewInt(double)) + b := new(big.Int).Sub(new(big.Int).SetBytes(v), big.NewInt(ether155V)) + c := new(big.Int).Add(a, big.NewInt(etherPre155V)) + txV = new(big.Int).Add(b, c) + } + + txR := big.NewInt(0).SetBytes(r) + txS := big.NewInt(0).SetBytes(s) + + return &types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: gas, + To: to, + Value: value, + Data: data, + V: txV, + R: txR, + S: txS, + }, nil +} + +// StoreTransactions is used by the sequencer to add processed transactions into +// an open batch. If the batch already has txs, the processedTxs must be a super +// set of the existing ones, preserving order. +func (s *State) StoreTransactions(ctx context.Context, batchNumber uint64, processedTxs []*ProcessTransactionResponse, dbTx pgx.Tx) error { + if dbTx == nil { + return ErrDBTxNil + } + + // check existing txs vs parameter txs + existingTxs, err := s.GetTxsHashesByBatchNumber(ctx, batchNumber, dbTx) + if err != nil { + return err + } + if err := CheckSupersetBatchTransactions(existingTxs, processedTxs); err != nil { + return err + } + + // Check if last batch is closed. Note that it's assumed that only the latest batch can be open + isBatchClosed, err := s.PostgresStorage.IsBatchClosed(ctx, batchNumber, dbTx) + if err != nil { + return err + } + if isBatchClosed { + return ErrBatchAlreadyClosed + } + + processingContext, err := s.GetProcessingContext(ctx, batchNumber, dbTx) + if err != nil { + return err + } + + firstTxToInsert := len(existingTxs) + + for i := firstTxToInsert; i < len(processedTxs); i++ { + processedTx := processedTxs[i] + // if the transaction has an intrinsic invalid tx error it means + // the transaction has not changed the state, so we don't store it + // and just move to the next + if executor.IsIntrinsicError(executor.RomErrorCode(processedTx.RomError)) { + continue + } + + lastL2Block, err := s.GetLastL2Block(ctx, dbTx) + if err != nil { + return err + } + + header := &types.Header{ + Number: new(big.Int).SetUint64(lastL2Block.Number().Uint64() + 1), + ParentHash: lastL2Block.Hash(), + Coinbase: processingContext.Coinbase, + Root: processedTx.StateRoot, + GasUsed: processedTx.GasUsed, + GasLimit: s.cfg.MaxCumulativeGasUsed, + Time: uint64(processingContext.Timestamp.Unix()), + } + transactions := []*types.Transaction{&processedTx.Tx} + + receipt := generateReceipt(header.Number, processedTx) + receipts := []*types.Receipt{receipt} + + // Create block to be able to calculate its hash + block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) + block.ReceivedAt = processingContext.Timestamp + + receipt.BlockHash = block.Hash() + + // Store L2 block and its transaction + if err := s.AddL2Block(ctx, batchNumber, block, receipts, dbTx); err != nil { + return err + } + } + return nil +} + +// DebugTransaction re-executes a tx to generate its trace +func (s *State) DebugTransaction(ctx context.Context, transactionHash common.Hash, traceConfig TraceConfig, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { + // gets the transaction + tx, err := s.GetTransactionByHash(ctx, transactionHash, dbTx) + if err != nil { + return nil, err + } + + // gets the tx receipt + receipt, err := s.GetTransactionReceipt(ctx, transactionHash, dbTx) + if err != nil { + return nil, err + } + + // gets the l2 block including the transaction + block, err := s.GetL2BlockByNumber(ctx, receipt.BlockNumber.Uint64(), dbTx) + if err != nil { + return nil, err + } + + // get the previous L2 Block + previousBlockNumber := uint64(0) + if receipt.BlockNumber.Uint64() > 0 { + previousBlockNumber = receipt.BlockNumber.Uint64() - 1 + } + previousBlock, err := s.GetL2BlockByNumber(ctx, previousBlockNumber, dbTx) + if err != nil { + return nil, err + } + + // generate batch l2 data for the transaction + batchL2Data, err := EncodeTransactions([]types.Transaction{*tx}) + if err != nil { + return nil, err + } + + // gets batch that including the l2 block + batch, err := s.GetBatchByL2BlockNumber(ctx, block.NumberU64(), dbTx) + if err != nil { + return nil, err + } + + // gets batch that including the previous l2 block + previousBatch, err := s.GetBatchByL2BlockNumber(ctx, previousBlock.NumberU64(), dbTx) + if err != nil { + return nil, err + } + + forkId := s.GetForkIDByBatchNumber(batch.BatchNumber) + + // Create Batch + traceConfigRequest := &pb.TraceConfig{ + TxHashToGenerateCallTrace: transactionHash.Bytes(), + TxHashToGenerateExecuteTrace: transactionHash.Bytes(), + // set the defaults to the maximum information we can have. + // this is needed to process custom tracers later + DisableStorage: cFalse, + DisableStack: cFalse, + EnableMemory: cTrue, + EnableReturnData: cTrue, + } + + // if the default tracer is used, then we review the information + // we want to have in the trace related to the parameters we received. + if traceConfig.IsDefaultTracer() { + if traceConfig.DisableStorage { + traceConfigRequest.DisableStorage = cTrue + } + if traceConfig.DisableStack { + traceConfigRequest.DisableStack = cTrue + } + if traceConfig.EnableMemory { + traceConfigRequest.EnableMemory = cTrue + } + if traceConfig.EnableReturnData { + traceConfigRequest.EnableReturnData = cTrue + } + } + + oldStateRoot := previousBlock.Root() + processBatchRequest := &pb.ProcessBatchRequest{ + OldBatchNum: batch.BatchNumber - 1, + OldStateRoot: oldStateRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + + BatchL2Data: batchL2Data, + GlobalExitRoot: batch.GlobalExitRoot.Bytes(), + EthTimestamp: uint64(batch.Timestamp.Unix()), + Coinbase: batch.Coinbase.String(), + UpdateMerkleTree: cFalse, + ChainId: s.cfg.ChainID, + ForkId: forkId, + TraceConfig: traceConfigRequest, + } + + // Send Batch to the Executor + startTime := time.Now() + processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) + endTime := time.Now() + if err != nil { + return nil, err + } else if processBatchResponse.Error != executor.EXECUTOR_ERROR_NO_ERROR { + err = executor.ExecutorErr(processBatchResponse.Error) + s.eventLog.LogExecutorError(ctx, processBatchResponse.Error, processBatchRequest) + return nil, err + } + + // //save process batch response file + // b, err := json.Marshal(processBatchResponse) + // if err != nil { + // return nil, err + // } + // filePath := "./processBatchResponse.json" + // err = os.WriteFile(filePath, b, 0644) + // if err != nil { + // return nil, err + // } + + txs, _, err := DecodeTxs(batchL2Data) + if err != nil && !errors.Is(err, ErrInvalidData) { + return nil, err + } + + for _, tx := range txs { + log.Debugf(tx.Hash().String()) + } + + convertedResponse, err := s.convertToProcessBatchResponse(txs, processBatchResponse) + if err != nil { + return nil, err + } + + // Sanity check + response := convertedResponse.Responses[0] + log.Debugf(response.TxHash.String()) + if response.TxHash != transactionHash { + return nil, fmt.Errorf("tx hash not found in executor response") + } + + result := &runtime.ExecutionResult{ + CreateAddress: response.CreateAddress, + GasLeft: response.GasLeft, + GasUsed: response.GasUsed, + ReturnValue: response.ReturnValue, + StateRoot: response.StateRoot.Bytes(), + StructLogs: response.ExecutionTrace, + ExecutorTrace: response.CallTrace, + } + + // if is the default trace, return the result + if traceConfig.IsDefaultTracer() { + return result, nil + } + + senderAddress, err := GetSender(*tx) + if err != nil { + return nil, err + } + + context := instrumentation.Context{ + From: senderAddress.String(), + Input: hex.EncodeToHex(tx.Data()), + Gas: strconv.FormatUint(tx.Gas(), encoding.Base10), + Value: tx.Value().String(), + Output: hex.EncodeToHex(result.ReturnValue), + GasPrice: tx.GasPrice().String(), + OldStateRoot: oldStateRoot.String(), + Time: uint64(endTime.Sub(startTime)), + GasUsed: strconv.FormatUint(result.GasUsed, encoding.Base10), + } + + // Fill trace context + if tx.To() == nil { + context.Type = "CREATE" + context.To = result.CreateAddress.Hex() + } else { + context.Type = "CALL" + context.To = tx.To().Hex() + } + + result.ExecutorTrace.Context = context + + gasPrice, ok := new(big.Int).SetString(context.GasPrice, encoding.Base10) + if !ok { + log.Errorf("debug transaction: failed to parse gasPrice") + return nil, fmt.Errorf("failed to parse gasPrice") + } + + tracerContext := &tracers.Context{ + BlockHash: receipt.BlockHash, + BlockNumber: receipt.BlockNumber, + TxIndex: int(receipt.TransactionIndex), + TxHash: transactionHash, + } + + var evmTracer tracers.Tracer + if traceConfig.Is4ByteTracer() { + evmTracer, err = native.NewFourByteTracer(tracerContext, traceConfig.TracerConfig) + if err != nil { + log.Errorf("debug transaction: failed to create 4byteTracer, err: %v", err) + return nil, fmt.Errorf("failed to create 4byteTracer, err: %v", err) + } + } else if traceConfig.IsCallTracer() { + evmTracer, err = native.NewCallTracer(tracerContext, traceConfig.TracerConfig) + if err != nil { + log.Errorf("debug transaction: failed to create callTracer, err: %v", err) + return nil, fmt.Errorf("failed to create callTracer, err: %v", err) + } + } else if traceConfig.IsNoopTracer() { + evmTracer, err = native.NewNoopTracer(tracerContext, traceConfig.TracerConfig) + if err != nil { + log.Errorf("debug transaction: failed to create noopTracer, err: %v", err) + return nil, fmt.Errorf("failed to create noopTracer, err: %v", err) + } + } else if traceConfig.IsPrestateTracer() { + evmTracer, err = native.NewPrestateTracer(tracerContext, traceConfig.TracerConfig) + if err != nil { + log.Errorf("debug transaction: failed to create prestateTracer, err: %v", err) + return nil, fmt.Errorf("failed to create prestateTracer, err: %v", err) + } + } else if traceConfig.IsJSCustomTracer() { + evmTracer, err = js.NewJsTracer(*traceConfig.Tracer, tracerContext, traceConfig.TracerConfig) + if err != nil { + log.Errorf("debug transaction: failed to create jsTracer, err: %v", err) + return nil, fmt.Errorf("failed to create jsTracer, err: %v", err) + } + } else { + return nil, fmt.Errorf("invalid tracer: %v, err: %v", traceConfig.Tracer, err) + } + + fakeDB := &FakeDB{State: s, stateRoot: batch.StateRoot.Bytes()} + evm := fakevm.NewFakeEVM(fakevm.BlockContext{BlockNumber: big.NewInt(1)}, fakevm.TxContext{GasPrice: gasPrice}, fakeDB, params.TestChainConfig, fakevm.Config{Debug: true, Tracer: evmTracer}) + + traceResult, err := s.ParseTheTraceUsingTheTracer(evm, result.ExecutorTrace, evmTracer) + if err != nil { + log.Errorf("debug transaction: failed parse the trace using the tracer: %v", err) + return nil, fmt.Errorf("failed parse the trace using the tracer: %v", err) + } + + result.ExecutorTraceResult = traceResult + + return result, nil +} + +// ParseTheTraceUsingTheTracer parses the given trace with the given tracer. +func (s *State) ParseTheTraceUsingTheTracer(evm *fakevm.FakeEVM, trace instrumentation.ExecutorTrace, tracer tracers.Tracer) (json.RawMessage, error) { + var previousStep instrumentation.Step + var previousOp, previousGas *big.Int + var previousError error + var stateRoot []byte + + contextGas, ok := new(big.Int).SetString(trace.Context.Gas, encoding.Base10) + if !ok { + log.Debugf("error while parsing contextGas") + return nil, ErrParsingExecutorTrace + } + value, ok := new(big.Int).SetString(trace.Context.Value, encoding.Base10) + if !ok { + log.Debugf("error while parsing value") + return nil, ErrParsingExecutorTrace + } + + tracer.CaptureTxStart(contextGas.Uint64()) + decodedInput, err := hex.DecodeHex(trace.Context.Input) + if err != nil { + log.Errorf("error while decoding context input from hex to bytes:, %v", err) + return nil, ErrParsingExecutorTrace + } + tracer.CaptureStart(evm, common.HexToAddress(trace.Context.From), common.HexToAddress(trace.Context.To), trace.Context.Type == "CREATE", decodedInput, contextGas.Uint64(), value) + + bigStateRoot, ok := new(big.Int).SetString(trace.Context.OldStateRoot, 0) + if !ok { + log.Debugf("error while parsing context oldStateRoot") + return nil, ErrParsingExecutorTrace + } + stateRoot = bigStateRoot.Bytes() + evm.StateDB.SetStateRoot(stateRoot) + + output := common.FromHex(trace.Context.Output) + + var stepError error + for i, step := range trace.Steps { + stepErrorMsg := strings.TrimSpace(step.Error) + if stepErrorMsg != "" { + stepError = fmt.Errorf(stepErrorMsg) + } + + gas, ok := new(big.Int).SetString(step.Gas, encoding.Base10) + if !ok { + log.Debugf("error while parsing step gas") + return nil, ErrParsingExecutorTrace + } + + gasCost, ok := new(big.Int).SetString(step.GasCost, encoding.Base10) + if !ok { + log.Debugf("error while parsing step gasCost") + return nil, ErrParsingExecutorTrace + } + + op, ok := new(big.Int).SetString(step.Op, 0) + if !ok { + log.Debugf("error while parsing step op") + return nil, ErrParsingExecutorTrace + } + + // set Stack + stack := fakevm.NewStack() + for _, stackContent := range step.Stack { + valueBigInt, ok := new(big.Int).SetString(stackContent, hex.Base) + if !ok { + log.Debugf("error while parsing stack valueBigInt") + return nil, ErrParsingExecutorTrace + } + value, _ := uint256.FromBig(valueBigInt) + stack.Push(value) + } + + // set Memory + memory := fakevm.NewMemory() + if len(step.Memory) > 0 { + memory.Resize(uint64(len(step.Memory))) + memory.Set(0, uint64(len(step.Memory)), step.Memory) + } else { + memory = fakevm.NewMemory() + } + + value := hex.DecodeBig(step.Contract.Value) + scope := &fakevm.ScopeContext{ + Contract: fakevm.NewContract(fakevm.NewAccount(common.HexToAddress(step.Contract.Caller)), fakevm.NewAccount(common.HexToAddress(step.Contract.Address)), value, gas.Uint64()), + Memory: memory, + Stack: stack, + } + + codeAddr := common.HexToAddress(step.Contract.Address) + scope.Contract.CodeAddr = &codeAddr + + // when a revert is detected, we stop the execution + if step.OpCode == "REVERT" { + stepError = fakevm.ErrExecutionReverted + break + } + + if previousStep.OpCode == "CALL" && step.Pc != 0 { + tracer.CaptureExit(step.ReturnData, gasCost.Uint64(), stepError) + } + + if step.OpCode != "CALL" || trace.Steps[i+1].Pc == 0 { + if stepError != nil { + tracer.CaptureFault(step.Pc, fakevm.OpCode(op.Uint64()), gas.Uint64(), gasCost.Uint64(), scope, step.Depth, stepError) + } else { + tracer.CaptureState(step.Pc, fakevm.OpCode(op.Uint64()), gas.Uint64(), gasCost.Uint64(), scope, step.ReturnData, step.Depth, nil) + } + } + + previousOpCodeCanBeSubCall := previousStep.OpCode == "CREATE" || + previousStep.OpCode == "CREATE2" || + previousStep.OpCode == "DELEGATECALL" || + previousStep.OpCode == "CALL" || + previousStep.OpCode == "STATICCALL" || + // deprecated ones + previousStep.OpCode == "CALLCODE" || + previousStep.OpCode == "SELFDESTRUCT" + + // when a sub call or create is detected, the next step contains the contract updated + if previousOpCodeCanBeSubCall { + // shadowing "value" to override its value without compromising the external code + value := value + // value is not carried over when the capture enter handles STATIC CALL + if previousStep.OpCode == "STATICCALL" { + value = nil + } + + // if the previous depth is the same as the current one, this means + // the sub call did not executed any other step and the + // context is back to the same level. This can happen with pre compiled executions. + if previousStep.Depth == step.Depth { + addr, input := s.getPreCompiledCallAddressAndInput(previousStep) + tracer.CaptureEnter(fakevm.OpCode(previousOp.Uint64()), common.HexToAddress(previousStep.Contract.Address), addr, input, previousGas.Uint64(), value) + previousStepGasCost, ok := new(big.Int).SetString(step.GasCost, encoding.Base10) + if !ok { + log.Debugf("error while parsing previous step gasCost") + return nil, ErrParsingExecutorTrace + } + tracer.CaptureExit(step.ReturnData, previousStepGasCost.Uint64(), previousError) + } else { + tracer.CaptureEnter(fakevm.OpCode(previousOp.Uint64()), common.HexToAddress(step.Contract.Caller), common.HexToAddress(step.Contract.Address), []byte(step.Contract.Input), previousGas.Uint64(), value) + } + } + + // returning from a call or create + if previousStep.Depth > step.Depth { + tracer.CaptureExit(step.ReturnData, gasCost.Uint64(), stepError) + } + + // set StateRoot + stateRoot = []byte(step.StateRoot) + evm.StateDB.SetStateRoot(stateRoot) + + // set previous step values + previousStep = step + previousOp = op + previousGas = gas + previousError = stepError + } + + gasUsed, ok := new(big.Int).SetString(trace.Context.GasUsed, encoding.Base10) + if !ok { + log.Debugf("error while parsing gasUsed") + return nil, ErrParsingExecutorTrace + } + + restGas := contextGas.Uint64() - gasUsed.Uint64() + tracer.CaptureTxEnd(restGas) + tracer.CaptureEnd(output, gasUsed.Uint64(), stepError) + + return tracer.GetResult() +} + +func (s *State) getPreCompiledCallAddressAndInput(step instrumentation.Step) (common.Address, []byte) { + if step.OpCode == "DELEGATECALL" || step.OpCode == "CALL" || step.OpCode == "STATICCALL" || step.OpCode == "CALLCODE" { + addrPos := len(step.Stack) - 1 - 1 + argsOffsetPos := addrPos - 1 + argsSizePos := argsOffsetPos - 1 + + // if the stack has the tx value, we skip it + stackHasValue := step.OpCode == "CALL" || step.OpCode == "CALLCODE" + if stackHasValue { + argsOffsetPos-- + argsSizePos-- + } + + addrEncoded := step.Stack[addrPos] + addr := common.HexToAddress("0x" + addrEncoded) + + argsOffsetEncoded := step.Stack[argsOffsetPos] + argsOffset := hex.DecodeUint64(argsOffsetEncoded) + + argsSizeEncoded := step.Stack[argsSizePos] + argsSize := hex.DecodeUint64(argsSizeEncoded) + input := make([]byte, argsSize) + copy(input[0:argsSize], step.Memory[argsOffset:argsOffset+argsSize]) + return addr, input + } else { + return common.HexToAddress(step.Contract.Address), []byte(step.Contract.Input) + } +} + +// PreProcessTransaction processes the transaction in order to calculate its zkCounters before adding it to the pool +func (s *State) PreProcessTransaction(ctx context.Context, tx *types.Transaction, dbTx pgx.Tx) (*ProcessBatchResponse, error) { + sender, err := GetSender(*tx) + if err != nil { + return nil, err + } + + response, err := s.internalProcessUnsignedTransaction(ctx, tx, sender, nil, false, dbTx) + if err != nil { + return nil, err + } + + return response, nil +} + +// ProcessUnsignedTransaction processes the given unsigned transaction. +func (s *State) ProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) (*runtime.ExecutionResult, error) { + result := new(runtime.ExecutionResult) + response, err := s.internalProcessUnsignedTransaction(ctx, tx, senderAddress, l2BlockNumber, noZKEVMCounters, dbTx) + if err != nil { + return nil, err + } + + r := response.Responses[0] + result.ReturnValue = r.ReturnValue + result.GasLeft = r.GasLeft + result.GasUsed = r.GasUsed + result.CreateAddress = r.CreateAddress + result.StateRoot = r.StateRoot.Bytes() + + if errors.Is(r.RomError, runtime.ErrExecutionReverted) { + result.Err = constructErrorFromRevert(r.RomError, r.ReturnValue) + } else { + result.Err = r.RomError + } + + return result, nil +} + +// ProcessUnsignedTransaction processes the given unsigned transaction. +func (s *State) internalProcessUnsignedTransaction(ctx context.Context, tx *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, noZKEVMCounters bool, dbTx pgx.Tx) (*ProcessBatchResponse, error) { + if s.executorClient == nil { + return nil, ErrExecutorNil + } + if s.tree == nil { + return nil, ErrStateTreeNil + } + lastBatches, l2BlockStateRoot, err := s.PostgresStorage.GetLastNBatchesByL2BlockNumber(ctx, l2BlockNumber, two, dbTx) + if err != nil { + return nil, err + } + + stateRoot := l2BlockStateRoot + if l2BlockNumber != nil { + l2Block, err := s.GetL2BlockByNumber(ctx, *l2BlockNumber, dbTx) + if err != nil { + return nil, err + } + stateRoot = l2Block.Root() + } + + loadedNonce, err := s.tree.GetNonce(ctx, senderAddress, stateRoot.Bytes()) + if err != nil { + return nil, err + } + nonce := loadedNonce.Uint64() + + // Get latest batch from the database to get globalExitRoot and Timestamp + lastBatch := lastBatches[0] + + // Get batch before latest to get state root and local exit root + previousBatch := lastBatches[0] + if len(lastBatches) > 1 { + previousBatch = lastBatches[1] + } + + timestamp := uint64(lastBatch.Timestamp.Unix()) + + if l2BlockNumber != nil { + latestL2BlockNumber, err := s.PostgresStorage.GetLastL2BlockNumber(ctx, dbTx) + if err != nil { + return nil, err + } + + if *l2BlockNumber == latestL2BlockNumber { + timestamp = uint64(time.Now().Unix()) + } + } + + batchL2Data, err := EncodeUnsignedTransaction(*tx, s.cfg.ChainID, &nonce) + if err != nil { + log.Errorf("error encoding unsigned transaction ", err) + return nil, err + } + + forkID := GetForkIDByBatchNumber(s.cfg.ForkIDIntervals, lastBatch.BatchNumber) + // Create Batch + processBatchRequest := &pb.ProcessBatchRequest{ + OldBatchNum: lastBatch.BatchNumber, + BatchL2Data: batchL2Data, + From: senderAddress.String(), + OldStateRoot: stateRoot.Bytes(), + GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + EthTimestamp: timestamp, + Coinbase: lastBatch.Coinbase.String(), + UpdateMerkleTree: cFalse, + ChainId: s.cfg.ChainID, + ForkId: forkID, + } + + if noZKEVMCounters { + processBatchRequest.NoCounters = cTrue + } + + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.OldBatchNum]: %v", processBatchRequest.OldBatchNum) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.From]: %v", processBatchRequest.From) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.globalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.OldAccInputHash]: %v", hex.EncodeToHex(processBatchRequest.OldAccInputHash)) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) + log.Debugf("internalProcessUnsignedTransaction[processBatchRequest.ForkId]: %v", processBatchRequest.ForkId) + + // Send Batch to the Executor + processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) + if err != nil { + // Log this error as an executor unspecified error + s.eventLog.LogExecutorError(ctx, pb.ExecutorError_EXECUTOR_ERROR_UNSPECIFIED, processBatchRequest) + log.Errorf("error processing unsigned transaction ", err) + return nil, err + } else if processBatchResponse.Error != executor.EXECUTOR_ERROR_NO_ERROR { + err = executor.ExecutorErr(processBatchResponse.Error) + s.eventLog.LogExecutorError(ctx, processBatchResponse.Error, processBatchRequest) + return nil, err + } + + response, err := s.convertToProcessBatchResponse([]types.Transaction{*tx}, processBatchResponse) + if err != nil { + return nil, err + } + + if processBatchResponse.Responses[0].Error != pb.RomError(executor.ROM_ERROR_NO_ERROR) { + err := executor.RomErr(processBatchResponse.Responses[0].Error) + if !isEVMRevertError(err) { + return response, err + } + } + + return response, nil +} + +// isContractCreation checks if the tx is a contract creation +func (s *State) isContractCreation(tx *types.Transaction) bool { + return tx.To() == nil && len(tx.Data()) > 0 +} + +// StoreTransaction is used by the sequencer to add process a transaction +func (s *State) StoreTransaction(ctx context.Context, batchNumber uint64, processedTx *ProcessTransactionResponse, coinbase common.Address, timestamp uint64, dbTx pgx.Tx) error { + if dbTx == nil { + return ErrDBTxNil + } + + // if the transaction has an intrinsic invalid tx error it means + // the transaction has not changed the state, so we don't store it + if executor.IsIntrinsicError(executor.RomErrorCode(processedTx.RomError)) { + return nil + } + + lastL2Block, err := s.GetLastL2Block(ctx, dbTx) + if err != nil { + return err + } + + header := &types.Header{ + Number: new(big.Int).SetUint64(lastL2Block.Number().Uint64() + 1), + ParentHash: lastL2Block.Hash(), + Coinbase: coinbase, + Root: processedTx.StateRoot, + GasUsed: processedTx.GasUsed, + GasLimit: s.cfg.MaxCumulativeGasUsed, + Time: timestamp, + } + transactions := []*types.Transaction{&processedTx.Tx} + + receipt := generateReceipt(header.Number, processedTx) + receipts := []*types.Receipt{receipt} + + // Create block to be able to calculate its hash + block := types.NewBlock(header, transactions, []*types.Header{}, receipts, &trie.StackTrie{}) + block.ReceivedAt = time.Unix(int64(timestamp), 0) + + receipt.BlockHash = block.Hash() + + // Store L2 block and its transaction + if err := s.AddL2Block(ctx, batchNumber, block, receipts, dbTx); err != nil { + return err + } + + return nil +} + +// CheckSupersetBatchTransactions verifies that processedTransactions is a +// superset of existingTxs and that the existing txs have the same order, +// returns a non-nil error if that is not the case. +func CheckSupersetBatchTransactions(existingTxHashes []common.Hash, processedTxs []*ProcessTransactionResponse) error { + if len(existingTxHashes) > len(processedTxs) { + return ErrExistingTxGreaterThanProcessedTx + } + for i, existingTxHash := range existingTxHashes { + if existingTxHash != processedTxs[i].TxHash { + return ErrOutOfOrderProcessedTx + } + } + return nil +} + +// EstimateGas for a transaction +func (s *State) EstimateGas(transaction *types.Transaction, senderAddress common.Address, l2BlockNumber *uint64, dbTx pgx.Tx) (uint64, []byte, error) { + const ethTransferGas = 21000 + + var lowEnd uint64 + var highEnd uint64 + + ctx := context.Background() + + lastBatches, l2BlockStateRoot, err := s.PostgresStorage.GetLastNBatchesByL2BlockNumber(ctx, l2BlockNumber, two, dbTx) + if err != nil { + return 0, nil, err + } + + // Get latest batch from the database to get globalExitRoot and Timestamp + lastBatch := lastBatches[0] + + // Get batch before latest to get state root and local exit root + previousBatch := lastBatches[0] + if len(lastBatches) > 1 { + previousBatch = lastBatches[1] + } + + lowEnd, err = core.IntrinsicGas(transaction.Data(), transaction.AccessList(), s.isContractCreation(transaction), true, false, false) + if err != nil { + return 0, nil, err + } + + if lowEnd == ethTransferGas && transaction.To() != nil { + code, err := s.tree.GetCode(ctx, *transaction.To(), l2BlockStateRoot.Bytes()) + if err != nil { + log.Warnf("error while getting transaction.to() code %v", err) + } else if len(code) == 0 { + return lowEnd, nil, nil + } + } + + if transaction.Gas() != 0 && transaction.Gas() > lowEnd { + highEnd = transaction.Gas() + } else { + highEnd = s.cfg.MaxCumulativeGasUsed + } + + var availableBalance *big.Int + + if senderAddress != ZeroAddress { + senderBalance, err := s.tree.GetBalance(ctx, senderAddress, l2BlockStateRoot.Bytes()) + if err != nil { + if errors.Is(err, ErrNotFound) { + senderBalance = big.NewInt(0) + } else { + return 0, nil, err + } + } + + availableBalance = new(big.Int).Set(senderBalance) + + if transaction.Value() != nil { + if transaction.Value().Cmp(availableBalance) > 0 { + return 0, nil, ErrInsufficientFunds + } + + availableBalance.Sub(availableBalance, transaction.Value()) + } + } + + if transaction.GasPrice().BitLen() != 0 && // Gas price has been set + availableBalance != nil && // Available balance is found + availableBalance.Cmp(big.NewInt(0)) > 0 { // Available balance > 0 + gasAllowance := new(big.Int).Div(availableBalance, transaction.GasPrice()) + + // Check the gas allowance for this account, make sure high end is capped to it + if gasAllowance.IsUint64() && highEnd > gasAllowance.Uint64() { + log.Debugf("Gas estimation high-end capped by allowance [%d]", gasAllowance.Uint64()) + highEnd = gasAllowance.Uint64() + } + } + + // Run the transaction with the specified gas value. + // Returns a status indicating if the transaction failed, if it was reverted and the accompanying error + testTransaction := func(gas uint64, shouldOmitErr bool) (failed, reverted bool, gasUsed uint64, returnValue []byte, err error) { + tx := types.NewTx(&types.LegacyTx{ + Nonce: transaction.Nonce(), + To: transaction.To(), + Value: transaction.Value(), + Gas: gas, + GasPrice: transaction.GasPrice(), + Data: transaction.Data(), + }) + + batchL2Data, err := EncodeUnsignedTransaction(*tx, s.cfg.ChainID, nil) + if err != nil { + log.Errorf("error encoding unsigned transaction ", err) + return false, false, gasUsed, nil, err + } + + forkID := GetForkIDByBatchNumber(s.cfg.ForkIDIntervals, lastBatch.BatchNumber) + // Create a batch to be sent to the executor + processBatchRequest := &pb.ProcessBatchRequest{ + OldBatchNum: lastBatch.BatchNumber, + BatchL2Data: batchL2Data, + From: senderAddress.String(), + OldStateRoot: l2BlockStateRoot.Bytes(), + GlobalExitRoot: lastBatch.GlobalExitRoot.Bytes(), + OldAccInputHash: previousBatch.AccInputHash.Bytes(), + EthTimestamp: uint64(lastBatch.Timestamp.Unix()), + Coinbase: lastBatch.Coinbase.String(), + UpdateMerkleTree: cFalse, + ChainId: s.cfg.ChainID, + ForkId: forkID, + } + + log.Debugf("EstimateGas[processBatchRequest.OldBatchNum]: %v", processBatchRequest.OldBatchNum) + // log.Debugf("EstimateGas[processBatchRequest.BatchL2Data]: %v", hex.EncodeToHex(processBatchRequest.BatchL2Data)) + log.Debugf("EstimateGas[processBatchRequest.From]: %v", processBatchRequest.From) + log.Debugf("EstimateGas[processBatchRequest.OldStateRoot]: %v", hex.EncodeToHex(processBatchRequest.OldStateRoot)) + log.Debugf("EstimateGas[processBatchRequest.globalExitRoot]: %v", hex.EncodeToHex(processBatchRequest.GlobalExitRoot)) + log.Debugf("EstimateGas[processBatchRequest.OldAccInputHash]: %v", hex.EncodeToHex(processBatchRequest.OldAccInputHash)) + log.Debugf("EstimateGas[processBatchRequest.EthTimestamp]: %v", processBatchRequest.EthTimestamp) + log.Debugf("EstimateGas[processBatchRequest.Coinbase]: %v", processBatchRequest.Coinbase) + log.Debugf("EstimateGas[processBatchRequest.UpdateMerkleTree]: %v", processBatchRequest.UpdateMerkleTree) + log.Debugf("EstimateGas[processBatchRequest.ChainId]: %v", processBatchRequest.ChainId) + log.Debugf("EstimateGas[processBatchRequest.ForkId]: %v", processBatchRequest.ForkId) + + txExecutionOnExecutorTime := time.Now() + processBatchResponse, err := s.executorClient.ProcessBatch(ctx, processBatchRequest) + log.Debugf("executor time: %vms", time.Since(txExecutionOnExecutorTime).Milliseconds()) + if err != nil { + log.Errorf("error estimating gas: %v", err) + return false, false, gasUsed, nil, err + } + gasUsed = processBatchResponse.Responses[0].GasUsed + if processBatchResponse.Error != executor.EXECUTOR_ERROR_NO_ERROR { + err = executor.ExecutorErr(processBatchResponse.Error) + s.eventLog.LogExecutorError(ctx, processBatchResponse.Error, processBatchRequest) + return false, false, gasUsed, nil, err + } + + // Check if an out of gas error happened during EVM execution + if processBatchResponse.Responses[0].Error != pb.RomError(executor.ROM_ERROR_NO_ERROR) { + err := executor.RomErr(processBatchResponse.Responses[0].Error) + + if (isGasEVMError(err) || isGasApplyError(err)) && shouldOmitErr { + // Specifying the transaction failed, but not providing an error + // is an indication that a valid error occurred due to low gas, + // which will increase the lower bound for the search + return true, false, gasUsed, nil, nil + } + + if isEVMRevertError(err) { + // The EVM reverted during execution, attempt to extract the + // error message and return it + returnValue := processBatchResponse.Responses[0].ReturnValue + return true, true, gasUsed, returnValue, constructErrorFromRevert(err, returnValue) + } + + return true, false, gasUsed, nil, err + } + + return false, false, gasUsed, nil, nil + } + + txExecutions := []time.Duration{} + var totalExecutionTime time.Duration + + // Check if the highEnd is a good value to make the transaction pass + failed, reverted, gasUsed, returnValue, err := testTransaction(highEnd, false) + log.Debugf("Estimate gas. Trying to execute TX with %v gas", highEnd) + if failed { + if reverted { + return 0, returnValue, err + } + + // The transaction shouldn't fail, for whatever reason, at highEnd + return 0, nil, fmt.Errorf( + "unable to apply transaction even for the highest gas limit %d: %w", + highEnd, + err, + ) + } + + if lowEnd < gasUsed { + lowEnd = gasUsed + } + + // Start the binary search for the lowest possible gas price + for (lowEnd < highEnd) && (highEnd-lowEnd) > 4096 { + txExecutionStart := time.Now() + mid := (lowEnd + highEnd) / uint64(two) + + log.Debugf("Estimate gas. Trying to execute TX with %v gas", mid) + + failed, reverted, _, _, testErr := testTransaction(mid, true) + executionTime := time.Since(txExecutionStart) + totalExecutionTime += executionTime + txExecutions = append(txExecutions, executionTime) + if testErr != nil && !reverted { + // Reverts are ignored in the binary search, but are checked later on + // during the execution for the optimal gas limit found + return 0, nil, testErr + } + + if failed { + // If the transaction failed => increase the gas + lowEnd = mid + 1 + } else { + // If the transaction didn't fail => make this ok value the high end + highEnd = mid + } + } + + executions := int64(len(txExecutions)) + if executions > 0 { + log.Infof("EstimateGas executed TX %v %d times in %d milliseconds", transaction.Hash(), executions, totalExecutionTime.Milliseconds()) + } else { + log.Error("Estimate gas. Tx not executed") + } + return highEnd, nil, nil +} + +// Checks if executor level valid gas errors occurred +func isGasApplyError(err error) bool { + return errors.Is(err, ErrNotEnoughIntrinsicGas) +} + +// Checks if EVM level valid gas errors occurred +func isGasEVMError(err error) bool { + return errors.Is(err, runtime.ErrOutOfGas) +} + +// Checks if the EVM reverted during execution +func isEVMRevertError(err error) bool { + return errors.Is(err, runtime.ErrExecutionReverted) +} diff --git a/state/types.go b/state/types.go index f90769a2cb..72e8c4c14e 100644 --- a/state/types.go +++ b/state/types.go @@ -1,39 +1,43 @@ package state import ( + "encoding/json" + "fmt" + "math/big" + "strings" + "time" + + "github.com/0xPolygonHermez/zkevm-node/state/metrics" "github.com/0xPolygonHermez/zkevm-node/state/runtime/instrumentation" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) -// ProcessBatchRequest represents a request to process a batch. -type ProcessBatchRequest struct { - BatchNum uint64 - Coinbase common.Address - BatchL2Data []byte - OldStateRoot common.Hash - GlobalExitRoot common.Hash - OldLocalExitRoot common.Hash - EthTimestamp uint64 - UpdateMerkleTree bool - GenerateExecuteTrace bool - GenerateCallTrace bool +// ProcessRequest represents the request of a batch process. +type ProcessRequest struct { + BatchNumber uint64 + GlobalExitRoot common.Hash + OldStateRoot common.Hash + OldAccInputHash common.Hash + Transactions []byte + Coinbase common.Address + Timestamp time.Time + Caller metrics.CallerLabel } // ProcessBatchResponse represents the response of a batch process. type ProcessBatchResponse struct { - CumulativeGasUsed uint64 - IsBatchProcessed bool - Responses []*ProcessTransactionResponse - NewStateRoot common.Hash - NewLocalExitRoot common.Hash - CntKeccakHashes uint32 - CntPoseidonHashes uint32 - CntPoseidonPaddings uint32 - CntMemAligns uint32 - CntArithmetics uint32 - CntBinaries uint32 - CntSteps uint32 + NewStateRoot common.Hash + NewAccInputHash common.Hash + NewLocalExitRoot common.Hash + NewBatchNumber uint64 + UsedZkCounters ZKCounters + Responses []*ProcessTransactionResponse + ExecutorError error + IsRomLevelError bool + IsExecutorLevelError bool + IsRomOOCError bool + ReadWriteAddresses map[common.Address]*InfoReadWrite } // ProcessTransactionResponse represents the response of a tx process. @@ -51,16 +55,16 @@ type ProcessTransactionResponse struct { GasUsed uint64 // GasRefunded is the total gas refunded as result of execution GasRefunded uint64 - // Error represents any error encountered during the execution - Error error + // RomError represents any error encountered during the execution + RomError error // CreateAddress is the new SC Address in case of SC creation CreateAddress common.Address // StateRoot is the State Root StateRoot common.Hash // Logs emitted by LOG opcode Logs []*types.Log - // IsProcessed indicates if this tx didn't fit into the batch - IsProcessed bool + // ChangesStateRoot indicates if this tx affects the state + ChangesStateRoot bool // Tx is the whole transaction object Tx types.Transaction // ExecutionTrace contains the traces produced in the execution @@ -68,3 +72,165 @@ type ProcessTransactionResponse struct { // CallTrace contains the call trace. CallTrace instrumentation.ExecutorTrace } + +// ZKCounters counters for the tx +type ZKCounters struct { + CumulativeGasUsed uint64 + UsedKeccakHashes uint32 + UsedPoseidonHashes uint32 + UsedPoseidonPaddings uint32 + UsedMemAligns uint32 + UsedArithmetics uint32 + UsedBinaries uint32 + UsedSteps uint32 +} + +// SumUp sum ups zk counters with passed tx zk counters +func (z *ZKCounters) SumUp(other ZKCounters) { + z.CumulativeGasUsed += other.CumulativeGasUsed + z.UsedKeccakHashes += other.UsedKeccakHashes + z.UsedPoseidonHashes += other.UsedPoseidonHashes + z.UsedPoseidonPaddings += other.UsedPoseidonPaddings + z.UsedMemAligns += other.UsedMemAligns + z.UsedArithmetics += other.UsedArithmetics + z.UsedBinaries += other.UsedBinaries + z.UsedSteps += other.UsedSteps +} + +// Sub subtract zk counters with passed zk counters (not safe) +func (z *ZKCounters) Sub(other ZKCounters) error { + // ZKCounters + if other.CumulativeGasUsed > z.CumulativeGasUsed { + return GetZKCounterError("CumulativeGasUsed") + } + if other.UsedKeccakHashes > z.UsedKeccakHashes { + return GetZKCounterError("UsedKeccakHashes") + } + if other.UsedPoseidonHashes > z.UsedPoseidonHashes { + return GetZKCounterError("UsedPoseidonHashes") + } + if other.UsedPoseidonPaddings > z.UsedPoseidonPaddings { + return fmt.Errorf("underflow ZKCounter: UsedPoseidonPaddings") + } + if other.UsedMemAligns > z.UsedMemAligns { + return GetZKCounterError("UsedMemAligns") + } + if other.UsedArithmetics > z.UsedArithmetics { + return GetZKCounterError("UsedArithmetics") + } + if other.UsedBinaries > z.UsedBinaries { + return GetZKCounterError("UsedBinaries") + } + if other.UsedSteps > z.UsedSteps { + return GetZKCounterError("UsedSteps") + } + + z.CumulativeGasUsed -= other.CumulativeGasUsed + z.UsedKeccakHashes -= other.UsedKeccakHashes + z.UsedPoseidonHashes -= other.UsedPoseidonHashes + z.UsedPoseidonPaddings -= other.UsedPoseidonPaddings + z.UsedMemAligns -= other.UsedMemAligns + z.UsedArithmetics -= other.UsedArithmetics + z.UsedBinaries -= other.UsedBinaries + z.UsedSteps -= other.UsedSteps + + return nil +} + +// BatchResources is a struct that contains the ZKEVM resources used by a batch/tx +type BatchResources struct { + ZKCounters ZKCounters + Bytes uint64 +} + +// Sub subtracts the batch resources from other +func (r *BatchResources) Sub(other BatchResources) error { + // Bytes + if other.Bytes > r.Bytes { + return ErrBatchResourceBytesUnderflow + } + bytesBackup := r.Bytes + r.Bytes -= other.Bytes + err := r.ZKCounters.Sub(other.ZKCounters) + if err != nil { + r.Bytes = bytesBackup + return NewBatchRemainingResourcesUnderflowError(err, err.Error()) + } + + return err +} + +// InfoReadWrite has information about modified addresses during the execution +type InfoReadWrite struct { + Address common.Address + Nonce *uint64 + Balance *big.Int +} + +// TraceConfig sets the debug configuration for the executor +type TraceConfig struct { + DisableStorage bool + DisableStack bool + EnableMemory bool + EnableReturnData bool + Tracer *string + TracerConfig json.RawMessage +} + +// IsDefaultTracer returns true when no custom tracer is set +func (t *TraceConfig) IsDefaultTracer() bool { + return t.Tracer == nil || *t.Tracer == "" +} + +// Is4ByteTracer returns true when should use 4byteTracer +func (t *TraceConfig) Is4ByteTracer() bool { + return t.Tracer != nil && *t.Tracer == "4byteTracer" +} + +// IsCallTracer returns true when should use callTracer +func (t *TraceConfig) IsCallTracer() bool { + return t.Tracer != nil && *t.Tracer == "callTracer" +} + +// IsNoopTracer returns true when should use noopTracer +func (t *TraceConfig) IsNoopTracer() bool { + return t.Tracer != nil && *t.Tracer == "noopTracer" +} + +// IsPrestateTracer returns true when should use prestateTracer +func (t *TraceConfig) IsPrestateTracer() bool { + return t.Tracer != nil && *t.Tracer == "prestateTracer" +} + +// IsJSCustomTracer returns true when should use js custom tracer +func (t *TraceConfig) IsJSCustomTracer() bool { + return t.Tracer != nil && strings.Contains(*t.Tracer, "result") && strings.Contains(*t.Tracer, "fault") +} + +// TrustedReorg represents a trusted reorg +type TrustedReorg struct { + BatchNumber uint64 + Reason string +} + +// HexToAddressPtr create an address from a hex and returns its pointer +func HexToAddressPtr(hex string) *common.Address { + a := common.HexToAddress(hex) + return &a +} + +// HexToHashPtr create a hash from a hex and returns its pointer +func HexToHashPtr(hex string) *common.Hash { + h := common.HexToHash(hex) + return &h +} + +// AddressPtr returns a pointer to the provided address +func AddressPtr(i common.Address) *common.Address { + return &i +} + +// HashPtr returns a pointer to the provided hash +func HashPtr(h common.Hash) *common.Hash { + return &h +} diff --git a/synchronizer/config.go b/synchronizer/config.go index aae801666e..5142aaef7b 100644 --- a/synchronizer/config.go +++ b/synchronizer/config.go @@ -8,7 +8,8 @@ import ( type Config struct { // SyncInterval is the delay interval between reading new rollup information SyncInterval types.Duration `mapstructure:"SyncInterval"` - // SyncChunkSize is the number of blocks to sync on each chunk SyncChunkSize uint64 `mapstructure:"SyncChunkSize"` + // TrustedSequencerURL is the rpc url to connect and sync the trusted state + TrustedSequencerURL string `mapstructure:"TrustedSequencerURL"` } diff --git a/synchronizer/interfaces.go b/synchronizer/interfaces.go index 088b3538f0..732b5d5f6b 100644 --- a/synchronizer/interfaces.go +++ b/synchronizer/interfaces.go @@ -5,19 +5,25 @@ import ( "math/big" "github.com/0xPolygonHermez/zkevm-node/etherman" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" ) // ethermanInterface contains the methods required to interact with ethereum. type ethermanInterface interface { - HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) + HeaderByNumber(ctx context.Context, number *big.Int) (*ethTypes.Header, error) GetRollupInfoByBlockRange(ctx context.Context, fromBlock uint64, toBlock *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error) - EthBlockByNumber(ctx context.Context, blockNumber uint64) (*types.Block, error) + EthBlockByNumber(ctx context.Context, blockNumber uint64) (*ethTypes.Block, error) GetLatestBatchNumber() (uint64, error) GetTrustedSequencerURL() (string, error) + VerifyGenBlockNumber(ctx context.Context, genBlockNumber uint64) (bool, error) + GetForks(ctx context.Context, genBlockNumber uint64) ([]state.ForkIDInterval, error) + GetLatestVerifiedBatchNum() (uint64, error) } // stateInterface gathers the methods required to interact with the state. @@ -32,17 +38,40 @@ type stateInterface interface { GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) ResetTrustedState(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error AddVirtualBatch(ctx context.Context, virtualBatch *state.VirtualBatch, dbTx pgx.Tx) error - // GetNextForcedBatches returns the next forcedBatches in FIFO order GetNextForcedBatches(ctx context.Context, nextForcedBatches int, dbTx pgx.Tx) ([]state.ForcedBatch, error) - AddBatchNumberInForcedBatch(ctx context.Context, forceBatchNumber, batchNumber uint64, dbTx pgx.Tx) error AddVerifiedBatch(ctx context.Context, verifiedBatch *state.VerifiedBatch, dbTx pgx.Tx) error - ProcessAndStoreClosedBatch(ctx context.Context, processingCtx state.ProcessingContext, encodedTxs []byte, dbTx pgx.Tx) error + ProcessAndStoreClosedBatch(ctx context.Context, processingCtx state.ProcessingContext, encodedTxs []byte, dbTx pgx.Tx, caller metrics.CallerLabel) (common.Hash, error) SetGenesis(ctx context.Context, block state.Block, genesis state.Genesis, dbTx pgx.Tx) ([]byte, error) OpenBatch(ctx context.Context, processingContext state.ProcessingContext, dbTx pgx.Tx) error CloseBatch(ctx context.Context, receipt state.ProcessingReceipt, dbTx pgx.Tx) error - ProcessSequencerBatch(ctx context.Context, batchNumber uint64, txs []types.Transaction, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) + ProcessSequencerBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) StoreTransactions(ctx context.Context, batchNum uint64, processedTxs []*state.ProcessTransactionResponse, dbTx pgx.Tx) error GetStateRootByBatchNumber(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (common.Hash, error) - + ExecuteBatch(ctx context.Context, batch state.Batch, updateMerkleTree bool, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) + GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) + GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) + AddSequence(ctx context.Context, sequence state.Sequence, dbTx pgx.Tx) error + AddAccumulatedInputHash(ctx context.Context, batchNum uint64, accInputHash common.Hash, dbTx pgx.Tx) error + AddTrustedReorg(ctx context.Context, trustedReorg *state.TrustedReorg, dbTx pgx.Tx) error + GetReorgedTransactions(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]*ethTypes.Transaction, error) + ResetForkID(ctx context.Context, batchNumber, forkID uint64, version string, dbTx pgx.Tx) error + GetForkIDTrustedReorgCount(ctx context.Context, forkID uint64, version string, dbTx pgx.Tx) (uint64, error) + UpdateForkIDIntervals(intervals []state.ForkIDInterval) + SetLastBatchInfoSeenOnEthereum(ctx context.Context, lastBatchNumberSeen, lastBatchNumberVerified uint64, dbTx pgx.Tx) error + SetInitSyncBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error BeginStateTransaction(ctx context.Context) (pgx.Tx, error) } + +type ethTxManager interface { + Reorg(ctx context.Context, fromBlockNumber uint64, dbTx pgx.Tx) error +} + +type poolInterface interface { + DeleteReorgedTransactions(ctx context.Context, txs []*ethTypes.Transaction) error + StoreTx(ctx context.Context, tx ethTypes.Transaction, ip string, isWIP bool) error +} + +type zkEVMClientInterface interface { + BatchNumber(ctx context.Context) (uint64, error) + BatchByNumber(ctx context.Context, number *big.Int) (*types.Batch, error) +} diff --git a/synchronizer/mock_dbtx.go b/synchronizer/mock_dbtx.go index a4f35b1305..730d38c936 100644 --- a/synchronizer/mock_dbtx.go +++ b/synchronizer/mock_dbtx.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package synchronizer @@ -21,6 +21,10 @@ func (_m *dbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { ret := _m.Called(ctx) var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { r0 = rf(ctx) } else { @@ -29,7 +33,6 @@ func (_m *dbTxMock) Begin(ctx context.Context) (pgx.Tx, error) { } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -88,13 +91,16 @@ func (_m *dbTxMock) CopyFrom(ctx context.Context, tableName pgx.Identifier, colu ret := _m.Called(ctx, tableName, columnNames, rowSrc) var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) (int64, error)); ok { + return rf(ctx, tableName, columnNames, rowSrc) + } if rf, ok := ret.Get(0).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) int64); ok { r0 = rf(ctx, tableName, columnNames, rowSrc) } else { r0 = ret.Get(0).(int64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, pgx.Identifier, []string, pgx.CopyFromSource) error); ok { r1 = rf(ctx, tableName, columnNames, rowSrc) } else { @@ -112,6 +118,10 @@ func (_m *dbTxMock) Exec(ctx context.Context, sql string, arguments ...interface ret := _m.Called(_ca...) var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, arguments...) + } if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgconn.CommandTag); ok { r0 = rf(ctx, sql, arguments...) } else { @@ -120,7 +130,6 @@ func (_m *dbTxMock) Exec(ctx context.Context, sql string, arguments ...interface } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { r1 = rf(ctx, sql, arguments...) } else { @@ -149,6 +158,10 @@ func (_m *dbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgco ret := _m.Called(ctx, name, sql) var r0 *pgconn.StatementDescription + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, string) (*pgconn.StatementDescription, error)); ok { + return rf(ctx, name, sql) + } if rf, ok := ret.Get(0).(func(context.Context, string, string) *pgconn.StatementDescription); ok { r0 = rf(ctx, name, sql) } else { @@ -157,7 +170,6 @@ func (_m *dbTxMock) Prepare(ctx context.Context, name string, sql string) (*pgco } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { r1 = rf(ctx, name, sql) } else { @@ -175,6 +187,10 @@ func (_m *dbTxMock) Query(ctx context.Context, sql string, args ...interface{}) ret := _m.Called(_ca...) var r0 pgx.Rows + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (pgx.Rows, error)); ok { + return rf(ctx, sql, args...) + } if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) pgx.Rows); ok { r0 = rf(ctx, sql, args...) } else { @@ -183,7 +199,6 @@ func (_m *dbTxMock) Query(ctx context.Context, sql string, args ...interface{}) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok { r1 = rf(ctx, sql, args...) } else { @@ -198,6 +213,10 @@ func (_m *dbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{ ret := _m.Called(ctx, sql, args, scans, f) var r0 pgconn.CommandTag + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) (pgconn.CommandTag, error)); ok { + return rf(ctx, sql, args, scans, f) + } if rf, ok := ret.Get(0).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) pgconn.CommandTag); ok { r0 = rf(ctx, sql, args, scans, f) } else { @@ -206,7 +225,6 @@ func (_m *dbTxMock) QueryFunc(ctx context.Context, sql string, args []interface{ } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, string, []interface{}, []interface{}, func(pgx.QueryFuncRow) error) error); ok { r1 = rf(ctx, sql, args, scans, f) } else { diff --git a/synchronizer/mock_etherman.go b/synchronizer/mock_etherman.go index 017a6cd90a..45b93cdca5 100644 --- a/synchronizer/mock_etherman.go +++ b/synchronizer/mock_etherman.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package synchronizer @@ -12,6 +12,8 @@ import ( mock "github.com/stretchr/testify/mock" + state "github.com/0xPolygonHermez/zkevm-node/state" + types "github.com/ethereum/go-ethereum/core/types" ) @@ -25,6 +27,10 @@ func (_m *ethermanMock) EthBlockByNumber(ctx context.Context, blockNumber uint64 ret := _m.Called(ctx, blockNumber) var r0 *types.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (*types.Block, error)); ok { + return rf(ctx, blockNumber) + } if rf, ok := ret.Get(0).(func(context.Context, uint64) *types.Block); ok { r0 = rf(ctx, blockNumber) } else { @@ -33,7 +39,6 @@ func (_m *ethermanMock) EthBlockByNumber(ctx context.Context, blockNumber uint64 } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { r1 = rf(ctx, blockNumber) } else { @@ -43,18 +48,71 @@ func (_m *ethermanMock) EthBlockByNumber(ctx context.Context, blockNumber uint64 return r0, r1 } +// GetForks provides a mock function with given fields: ctx, genBlockNumber +func (_m *ethermanMock) GetForks(ctx context.Context, genBlockNumber uint64) ([]state.ForkIDInterval, error) { + ret := _m.Called(ctx, genBlockNumber) + + var r0 []state.ForkIDInterval + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) ([]state.ForkIDInterval, error)); ok { + return rf(ctx, genBlockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) []state.ForkIDInterval); ok { + r0 = rf(ctx, genBlockNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]state.ForkIDInterval) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, genBlockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetLatestBatchNumber provides a mock function with given fields: func (_m *ethermanMock) GetLatestBatchNumber() (uint64, error) { ret := _m.Called() var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func() (uint64, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() uint64); ok { r0 = rf() } else { r0 = ret.Get(0).(uint64) } + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLatestVerifiedBatchNum provides a mock function with given fields: +func (_m *ethermanMock) GetLatestVerifiedBatchNum() (uint64, error) { + ret := _m.Called() + + var r0 uint64 var r1 error + if rf, ok := ret.Get(0).(func() (uint64, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() uint64); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(uint64) + } + if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -69,6 +127,11 @@ func (_m *ethermanMock) GetRollupInfoByBlockRange(ctx context.Context, fromBlock ret := _m.Called(ctx, fromBlock, toBlock) var r0 []etherman.Block + var r1 map[common.Hash][]etherman.Order + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) ([]etherman.Block, map[common.Hash][]etherman.Order, error)); ok { + return rf(ctx, fromBlock, toBlock) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) []etherman.Block); ok { r0 = rf(ctx, fromBlock, toBlock) } else { @@ -77,7 +140,6 @@ func (_m *ethermanMock) GetRollupInfoByBlockRange(ctx context.Context, fromBlock } } - var r1 map[common.Hash][]etherman.Order if rf, ok := ret.Get(1).(func(context.Context, uint64, *uint64) map[common.Hash][]etherman.Order); ok { r1 = rf(ctx, fromBlock, toBlock) } else { @@ -86,7 +148,6 @@ func (_m *ethermanMock) GetRollupInfoByBlockRange(ctx context.Context, fromBlock } } - var r2 error if rf, ok := ret.Get(2).(func(context.Context, uint64, *uint64) error); ok { r2 = rf(ctx, fromBlock, toBlock) } else { @@ -101,13 +162,16 @@ func (_m *ethermanMock) GetTrustedSequencerURL() (string, error) { ret := _m.Called() var r0 string + var r1 error + if rf, ok := ret.Get(0).(func() (string, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() string); ok { r0 = rf() } else { r0 = ret.Get(0).(string) } - var r1 error if rf, ok := ret.Get(1).(func() error); ok { r1 = rf() } else { @@ -122,6 +186,10 @@ func (_m *ethermanMock) HeaderByNumber(ctx context.Context, number *big.Int) (*t ret := _m.Called(ctx, number) var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Header, error)); ok { + return rf(ctx, number) + } if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Header); ok { r0 = rf(ctx, number) } else { @@ -130,7 +198,6 @@ func (_m *ethermanMock) HeaderByNumber(ctx context.Context, number *big.Int) (*t } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { r1 = rf(ctx, number) } else { @@ -140,6 +207,30 @@ func (_m *ethermanMock) HeaderByNumber(ctx context.Context, number *big.Int) (*t return r0, r1 } +// VerifyGenBlockNumber provides a mock function with given fields: ctx, genBlockNumber +func (_m *ethermanMock) VerifyGenBlockNumber(ctx context.Context, genBlockNumber uint64) (bool, error) { + ret := _m.Called(ctx, genBlockNumber) + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64) (bool, error)); ok { + return rf(ctx, genBlockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64) bool); ok { + r0 = rf(ctx, genBlockNumber) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64) error); ok { + r1 = rf(ctx, genBlockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + type mockConstructorTestingTnewEthermanMock interface { mock.TestingT Cleanup(func()) diff --git a/synchronizer/mock_ethtxmanager.go b/synchronizer/mock_ethtxmanager.go new file mode 100644 index 0000000000..31f6dd3ef0 --- /dev/null +++ b/synchronizer/mock_ethtxmanager.go @@ -0,0 +1,44 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package synchronizer + +import ( + context "context" + + pgx "github.com/jackc/pgx/v4" + mock "github.com/stretchr/testify/mock" +) + +// ethTxManagerMock is an autogenerated mock type for the ethTxManager type +type ethTxManagerMock struct { + mock.Mock +} + +// Reorg provides a mock function with given fields: ctx, fromBlockNumber, dbTx +func (_m *ethTxManagerMock) Reorg(ctx context.Context, fromBlockNumber uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, fromBlockNumber, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, fromBlockNumber, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTnewEthTxManagerMock interface { + mock.TestingT + Cleanup(func()) +} + +// newEthTxManagerMock creates a new instance of ethTxManagerMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newEthTxManagerMock(t mockConstructorTestingTnewEthTxManagerMock) *ethTxManagerMock { + mock := ðTxManagerMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/synchronizer/mock_pool.go b/synchronizer/mock_pool.go new file mode 100644 index 0000000000..0db2e31cb0 --- /dev/null +++ b/synchronizer/mock_pool.go @@ -0,0 +1,59 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package synchronizer + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// poolMock is an autogenerated mock type for the poolInterface type +type poolMock struct { + mock.Mock +} + +// DeleteReorgedTransactions provides a mock function with given fields: ctx, txs +func (_m *poolMock) DeleteReorgedTransactions(ctx context.Context, txs []*types.Transaction) error { + ret := _m.Called(ctx, txs) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []*types.Transaction) error); ok { + r0 = rf(ctx, txs) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// StoreTx provides a mock function with given fields: ctx, tx, ip, isWIP +func (_m *poolMock) StoreTx(ctx context.Context, tx types.Transaction, ip string, isWIP bool) error { + ret := _m.Called(ctx, tx, ip, isWIP) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.Transaction, string, bool) error); ok { + r0 = rf(ctx, tx, ip, isWIP) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +type mockConstructorTestingTnewPoolMock interface { + mock.TestingT + Cleanup(func()) +} + +// newPoolMock creates a new instance of poolMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newPoolMock(t mockConstructorTestingTnewPoolMock) *poolMock { + mock := &poolMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/synchronizer/mock_state.go b/synchronizer/mock_state.go index f6a743512d..8e05a7d1ba 100644 --- a/synchronizer/mock_state.go +++ b/synchronizer/mock_state.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.22.1. DO NOT EDIT. package synchronizer @@ -7,8 +7,12 @@ import ( common "github.com/ethereum/go-ethereum/common" + metrics "github.com/0xPolygonHermez/zkevm-node/state/metrics" + mock "github.com/stretchr/testify/mock" + pb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" + pgx "github.com/jackc/pgx/v4" state "github.com/0xPolygonHermez/zkevm-node/state" @@ -21,13 +25,13 @@ type stateMock struct { mock.Mock } -// AddBatchNumberInForcedBatch provides a mock function with given fields: ctx, forceBatchNumber, batchNumber, dbTx -func (_m *stateMock) AddBatchNumberInForcedBatch(ctx context.Context, forceBatchNumber uint64, batchNumber uint64, dbTx pgx.Tx) error { - ret := _m.Called(ctx, forceBatchNumber, batchNumber, dbTx) +// AddAccumulatedInputHash provides a mock function with given fields: ctx, batchNum, accInputHash, dbTx +func (_m *stateMock) AddAccumulatedInputHash(ctx context.Context, batchNum uint64, accInputHash common.Hash, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNum, accInputHash, dbTx) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { - r0 = rf(ctx, forceBatchNumber, batchNumber, dbTx) + if rf, ok := ret.Get(0).(func(context.Context, uint64, common.Hash, pgx.Tx) error); ok { + r0 = rf(ctx, batchNum, accInputHash, dbTx) } else { r0 = ret.Error(0) } @@ -77,6 +81,34 @@ func (_m *stateMock) AddGlobalExitRoot(ctx context.Context, exitRoot *state.Glob return r0 } +// AddSequence provides a mock function with given fields: ctx, sequence, dbTx +func (_m *stateMock) AddSequence(ctx context.Context, sequence state.Sequence, dbTx pgx.Tx) error { + ret := _m.Called(ctx, sequence, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, state.Sequence, pgx.Tx) error); ok { + r0 = rf(ctx, sequence, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// AddTrustedReorg provides a mock function with given fields: ctx, trustedReorg, dbTx +func (_m *stateMock) AddTrustedReorg(ctx context.Context, trustedReorg *state.TrustedReorg, dbTx pgx.Tx) error { + ret := _m.Called(ctx, trustedReorg, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *state.TrustedReorg, pgx.Tx) error); ok { + r0 = rf(ctx, trustedReorg, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // AddVerifiedBatch provides a mock function with given fields: ctx, verifiedBatch, dbTx func (_m *stateMock) AddVerifiedBatch(ctx context.Context, verifiedBatch *state.VerifiedBatch, dbTx pgx.Tx) error { ret := _m.Called(ctx, verifiedBatch, dbTx) @@ -110,6 +142,10 @@ func (_m *stateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) ret := _m.Called(ctx) var r0 pgx.Tx + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (pgx.Tx, error)); ok { + return rf(ctx) + } if rf, ok := ret.Get(0).(func(context.Context) pgx.Tx); ok { r0 = rf(ctx) } else { @@ -118,7 +154,6 @@ func (_m *stateMock) BeginStateTransaction(ctx context.Context) (pgx.Tx, error) } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { r1 = rf(ctx) } else { @@ -142,11 +177,41 @@ func (_m *stateMock) CloseBatch(ctx context.Context, receipt state.ProcessingRec return r0 } +// ExecuteBatch provides a mock function with given fields: ctx, batch, updateMerkleTree, dbTx +func (_m *stateMock) ExecuteBatch(ctx context.Context, batch state.Batch, updateMerkleTree bool, dbTx pgx.Tx) (*pb.ProcessBatchResponse, error) { + ret := _m.Called(ctx, batch, updateMerkleTree, dbTx) + + var r0 *pb.ProcessBatchResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, state.Batch, bool, pgx.Tx) (*pb.ProcessBatchResponse, error)); ok { + return rf(ctx, batch, updateMerkleTree, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, state.Batch, bool, pgx.Tx) *pb.ProcessBatchResponse); ok { + r0 = rf(ctx, batch, updateMerkleTree, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pb.ProcessBatchResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, state.Batch, bool, pgx.Tx) error); ok { + r1 = rf(ctx, batch, updateMerkleTree, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetBatchByNumber provides a mock function with given fields: ctx, batchNumber, dbTx func (_m *stateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error) { ret := _m.Called(ctx, batchNumber, dbTx) var r0 *state.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Batch, error)); ok { + return rf(ctx, batchNumber, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Batch); ok { r0 = rf(ctx, batchNumber, dbTx) } else { @@ -155,7 +220,6 @@ func (_m *stateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, d } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { r1 = rf(ctx, batchNumber, dbTx) } else { @@ -165,18 +229,45 @@ func (_m *stateMock) GetBatchByNumber(ctx context.Context, batchNumber uint64, d return r0, r1 } +// GetForkIDTrustedReorgCount provides a mock function with given fields: ctx, forkID, version, dbTx +func (_m *stateMock) GetForkIDTrustedReorgCount(ctx context.Context, forkID uint64, version string, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, forkID, version, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, string, pgx.Tx) (uint64, error)); ok { + return rf(ctx, forkID, version, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, string, pgx.Tx) uint64); ok { + r0 = rf(ctx, forkID, version, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, string, pgx.Tx) error); ok { + r1 = rf(ctx, forkID, version, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetLastBatchNumber provides a mock function with given fields: ctx, dbTx func (_m *stateMock) GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) { ret := _m.Called(ctx, dbTx) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { r0 = rf(ctx, dbTx) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { r1 = rf(ctx, dbTx) } else { @@ -191,6 +282,10 @@ func (_m *stateMock) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Bloc ret := _m.Called(ctx, dbTx) var r0 *state.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.Block, error)); ok { + return rf(ctx, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.Block); ok { r0 = rf(ctx, dbTx) } else { @@ -199,7 +294,56 @@ func (_m *stateMock) GetLastBlock(ctx context.Context, dbTx pgx.Tx) (*state.Bloc } } + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVerifiedBatch provides a mock function with given fields: ctx, dbTx +func (_m *stateMock) GetLastVerifiedBatch(ctx context.Context, dbTx pgx.Tx) (*state.VerifiedBatch, error) { + ret := _m.Called(ctx, dbTx) + + var r0 *state.VerifiedBatch var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (*state.VerifiedBatch, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) *state.VerifiedBatch); ok { + r0 = rf(ctx, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*state.VerifiedBatch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { + r1 = rf(ctx, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLastVirtualBatchNum provides a mock function with given fields: ctx, dbTx +func (_m *stateMock) GetLastVirtualBatchNum(ctx context.Context, dbTx pgx.Tx) (uint64, error) { + ret := _m.Called(ctx, dbTx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) (uint64, error)); ok { + return rf(ctx, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, pgx.Tx) uint64); ok { + r0 = rf(ctx, dbTx) + } else { + r0 = ret.Get(0).(uint64) + } + if rf, ok := ret.Get(1).(func(context.Context, pgx.Tx) error); ok { r1 = rf(ctx, dbTx) } else { @@ -214,6 +358,10 @@ func (_m *stateMock) GetNextForcedBatches(ctx context.Context, nextForcedBatches ret := _m.Called(ctx, nextForcedBatches, dbTx) var r0 []state.ForcedBatch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int, pgx.Tx) ([]state.ForcedBatch, error)); ok { + return rf(ctx, nextForcedBatches, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, int, pgx.Tx) []state.ForcedBatch); ok { r0 = rf(ctx, nextForcedBatches, dbTx) } else { @@ -222,7 +370,6 @@ func (_m *stateMock) GetNextForcedBatches(ctx context.Context, nextForcedBatches } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, int, pgx.Tx) error); ok { r1 = rf(ctx, nextForcedBatches, dbTx) } else { @@ -237,6 +384,10 @@ func (_m *stateMock) GetPreviousBlock(ctx context.Context, offset uint64, dbTx p ret := _m.Called(ctx, offset, dbTx) var r0 *state.Block + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (*state.Block, error)); ok { + return rf(ctx, offset, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) *state.Block); ok { r0 = rf(ctx, offset, dbTx) } else { @@ -245,7 +396,6 @@ func (_m *stateMock) GetPreviousBlock(ctx context.Context, offset uint64, dbTx p } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { r1 = rf(ctx, offset, dbTx) } else { @@ -255,11 +405,41 @@ func (_m *stateMock) GetPreviousBlock(ctx context.Context, offset uint64, dbTx p return r0, r1 } +// GetReorgedTransactions provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *stateMock) GetReorgedTransactions(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) ([]*types.Transaction, error) { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 []*types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) ([]*types.Transaction, error)); ok { + return rf(ctx, batchNumber, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) []*types.Transaction); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, dbTx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetStateRootByBatchNumber provides a mock function with given fields: ctx, batchNum, dbTx func (_m *stateMock) GetStateRootByBatchNumber(ctx context.Context, batchNum uint64, dbTx pgx.Tx) (common.Hash, error) { ret := _m.Called(ctx, batchNum, dbTx) var r0 common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) (common.Hash, error)); ok { + return rf(ctx, batchNum, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) common.Hash); ok { r0 = rf(ctx, batchNum, dbTx) } else { @@ -268,7 +448,6 @@ func (_m *stateMock) GetStateRootByBatchNumber(ctx context.Context, batchNum uin } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, uint64, pgx.Tx) error); ok { r1 = rf(ctx, batchNum, dbTx) } else { @@ -292,36 +471,51 @@ func (_m *stateMock) OpenBatch(ctx context.Context, processingContext state.Proc return r0 } -// ProcessAndStoreClosedBatch provides a mock function with given fields: ctx, processingCtx, encodedTxs, dbTx -func (_m *stateMock) ProcessAndStoreClosedBatch(ctx context.Context, processingCtx state.ProcessingContext, encodedTxs []byte, dbTx pgx.Tx) error { - ret := _m.Called(ctx, processingCtx, encodedTxs, dbTx) +// ProcessAndStoreClosedBatch provides a mock function with given fields: ctx, processingCtx, encodedTxs, dbTx, caller +func (_m *stateMock) ProcessAndStoreClosedBatch(ctx context.Context, processingCtx state.ProcessingContext, encodedTxs []byte, dbTx pgx.Tx, caller metrics.CallerLabel) (common.Hash, error) { + ret := _m.Called(ctx, processingCtx, encodedTxs, dbTx, caller) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingContext, []byte, pgx.Tx) error); ok { - r0 = rf(ctx, processingCtx, encodedTxs, dbTx) + var r0 common.Hash + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingContext, []byte, pgx.Tx, metrics.CallerLabel) (common.Hash, error)); ok { + return rf(ctx, processingCtx, encodedTxs, dbTx, caller) + } + if rf, ok := ret.Get(0).(func(context.Context, state.ProcessingContext, []byte, pgx.Tx, metrics.CallerLabel) common.Hash); ok { + r0 = rf(ctx, processingCtx, encodedTxs, dbTx, caller) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Hash) + } } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, state.ProcessingContext, []byte, pgx.Tx, metrics.CallerLabel) error); ok { + r1 = rf(ctx, processingCtx, encodedTxs, dbTx, caller) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } -// ProcessSequencerBatch provides a mock function with given fields: ctx, batchNumber, txs, dbTx -func (_m *stateMock) ProcessSequencerBatch(ctx context.Context, batchNumber uint64, txs []types.Transaction, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) { - ret := _m.Called(ctx, batchNumber, txs, dbTx) +// ProcessSequencerBatch provides a mock function with given fields: ctx, batchNumber, batchL2Data, caller, dbTx +func (_m *stateMock) ProcessSequencerBatch(ctx context.Context, batchNumber uint64, batchL2Data []byte, caller metrics.CallerLabel, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) { + ret := _m.Called(ctx, batchNumber, batchL2Data, caller, dbTx) var r0 *state.ProcessBatchResponse - if rf, ok := ret.Get(0).(func(context.Context, uint64, []types.Transaction, pgx.Tx) *state.ProcessBatchResponse); ok { - r0 = rf(ctx, batchNumber, txs, dbTx) + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) (*state.ProcessBatchResponse, error)); ok { + return rf(ctx, batchNumber, batchL2Data, caller, dbTx) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) *state.ProcessBatchResponse); ok { + r0 = rf(ctx, batchNumber, batchL2Data, caller, dbTx) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*state.ProcessBatchResponse) } } - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, uint64, []types.Transaction, pgx.Tx) error); ok { - r1 = rf(ctx, batchNumber, txs, dbTx) + if rf, ok := ret.Get(1).(func(context.Context, uint64, []byte, metrics.CallerLabel, pgx.Tx) error); ok { + r1 = rf(ctx, batchNumber, batchL2Data, caller, dbTx) } else { r1 = ret.Error(1) } @@ -343,6 +537,20 @@ func (_m *stateMock) Reset(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) return r0 } +// ResetForkID provides a mock function with given fields: ctx, batchNumber, forkID, version, dbTx +func (_m *stateMock) ResetForkID(ctx context.Context, batchNumber uint64, forkID uint64, version string, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, forkID, version, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, string, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, forkID, version, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // ResetTrustedState provides a mock function with given fields: ctx, batchNumber, dbTx func (_m *stateMock) ResetTrustedState(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { ret := _m.Called(ctx, batchNumber, dbTx) @@ -362,6 +570,10 @@ func (_m *stateMock) SetGenesis(ctx context.Context, block state.Block, genesis ret := _m.Called(ctx, block, genesis, dbTx) var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, state.Block, state.Genesis, pgx.Tx) ([]byte, error)); ok { + return rf(ctx, block, genesis, dbTx) + } if rf, ok := ret.Get(0).(func(context.Context, state.Block, state.Genesis, pgx.Tx) []byte); ok { r0 = rf(ctx, block, genesis, dbTx) } else { @@ -370,7 +582,6 @@ func (_m *stateMock) SetGenesis(ctx context.Context, block state.Block, genesis } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, state.Block, state.Genesis, pgx.Tx) error); ok { r1 = rf(ctx, block, genesis, dbTx) } else { @@ -380,6 +591,34 @@ func (_m *stateMock) SetGenesis(ctx context.Context, block state.Block, genesis return r0, r1 } +// SetInitSyncBatch provides a mock function with given fields: ctx, batchNumber, dbTx +func (_m *stateMock) SetInitSyncBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, batchNumber, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, batchNumber, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SetLastBatchInfoSeenOnEthereum provides a mock function with given fields: ctx, lastBatchNumberSeen, lastBatchNumberVerified, dbTx +func (_m *stateMock) SetLastBatchInfoSeenOnEthereum(ctx context.Context, lastBatchNumberSeen uint64, lastBatchNumberVerified uint64, dbTx pgx.Tx) error { + ret := _m.Called(ctx, lastBatchNumberSeen, lastBatchNumberVerified, dbTx) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, uint64, pgx.Tx) error); ok { + r0 = rf(ctx, lastBatchNumberSeen, lastBatchNumberVerified, dbTx) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // StoreTransactions provides a mock function with given fields: ctx, batchNum, processedTxs, dbTx func (_m *stateMock) StoreTransactions(ctx context.Context, batchNum uint64, processedTxs []*state.ProcessTransactionResponse, dbTx pgx.Tx) error { ret := _m.Called(ctx, batchNum, processedTxs, dbTx) @@ -394,6 +633,11 @@ func (_m *stateMock) StoreTransactions(ctx context.Context, batchNum uint64, pro return r0 } +// UpdateForkIDIntervals provides a mock function with given fields: intervals +func (_m *stateMock) UpdateForkIDIntervals(intervals []state.ForkIDInterval) { + _m.Called(intervals) +} + type mockConstructorTestingTnewStateMock interface { mock.TestingT Cleanup(func()) diff --git a/synchronizer/mock_zkevmclient.go b/synchronizer/mock_zkevmclient.go new file mode 100644 index 0000000000..cc65d007a2 --- /dev/null +++ b/synchronizer/mock_zkevmclient.go @@ -0,0 +1,82 @@ +// Code generated by mockery v2.22.1. DO NOT EDIT. + +package synchronizer + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" + + types "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" +) + +// zkEVMClientMock is an autogenerated mock type for the zkEVMClientInterface type +type zkEVMClientMock struct { + mock.Mock +} + +// BatchByNumber provides a mock function with given fields: ctx, number +func (_m *zkEVMClientMock) BatchByNumber(ctx context.Context, number *big.Int) (*types.Batch, error) { + ret := _m.Called(ctx, number) + + var r0 *types.Batch + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Batch, error)); ok { + return rf(ctx, number) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Batch); ok { + r0 = rf(ctx, number) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Batch) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, number) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BatchNumber provides a mock function with given fields: ctx +func (_m *zkEVMClientMock) BatchNumber(ctx context.Context) (uint64, error) { + ret := _m.Called(ctx) + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (uint64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) uint64); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTnewZkEVMClientMock interface { + mock.TestingT + Cleanup(func()) +} + +// newZkEVMClientMock creates a new instance of zkEVMClientMock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func newZkEVMClientMock(t mockConstructorTestingTnewZkEVMClientMock) *zkEVMClientMock { + mock := &zkEVMClientMock{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go index fbfd6cff01..db7f94744a 100644 --- a/synchronizer/synchronizer.go +++ b/synchronizer/synchronizer.go @@ -2,23 +2,21 @@ package synchronizer import ( "context" - "encoding/json" "errors" "fmt" "math/big" + "strings" "time" "github.com/0xPolygonHermez/zkevm-node/etherman" "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" - "google.golang.org/protobuf/types/known/emptypb" ) // Synchronizer connects L1 and L2 @@ -32,9 +30,11 @@ type ClientSynchronizer struct { isTrustedSequencer bool etherMan ethermanInterface state stateInterface + pool poolInterface + ethTxManager ethTxManager + zkEVMClient zkEVMClientInterface ctx context.Context cancelCtx context.CancelFunc - genBlockNumber uint64 genesis state.Genesis cfg Config } @@ -44,7 +44,9 @@ func NewSynchronizer( isTrustedSequencer bool, ethMan ethermanInterface, st stateInterface, - genBlockNumber uint64, + pool poolInterface, + ethTxManager ethTxManager, + zkEVMClient zkEVMClientInterface, genesis state.Genesis, cfg Config) (Synchronizer, error) { ctx, cancel := context.WithCancel(context.Background()) @@ -53,9 +55,11 @@ func NewSynchronizer( isTrustedSequencer: isTrustedSequencer, state: st, etherMan: ethMan, + pool: pool, ctx: ctx, cancelCtx: cancel, - genBlockNumber: genBlockNumber, + ethTxManager: ethTxManager, + zkEVMClient: zkEVMClient, genesis: genesis, cfg: cfg, }, nil @@ -71,15 +75,41 @@ func (s *ClientSynchronizer) Sync() error { log.Info("Sync started") dbTx, err := s.state.BeginStateTransaction(s.ctx) if err != nil { - log.Fatalf("error creating db transaction to get latest block") + log.Errorf("error creating db transaction to get latest block. Error: %v", err) + return err } lastEthBlockSynced, err := s.state.GetLastBlock(s.ctx, dbTx) if err != nil { if errors.Is(err, state.ErrStateNotSynchronized) { - log.Info("State is empty, setting genesis block") - header, err := s.etherMan.HeaderByNumber(s.ctx, big.NewInt(0).SetUint64(s.genBlockNumber)) + log.Info("State is empty, verifying genesis block") + valid, err := s.etherMan.VerifyGenBlockNumber(s.ctx, s.genesis.GenesisBlockNum) + if err != nil { + log.Error("error checking genesis block number. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr + } + return err + } else if !valid { + log.Error("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed") + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v", rollbackErr) + return rollbackErr + } + return fmt.Errorf("genesis Block number configured is not valid. It is required the block number where the PolygonZkEVM smc was deployed") + } + log.Info("Setting genesis block") + header, err := s.etherMan.HeaderByNumber(s.ctx, big.NewInt(0).SetUint64(s.genesis.GenesisBlockNum)) if err != nil { - log.Fatal("error getting l1 block header for block ", s.genBlockNumber, " : ", err) + log.Errorf("error getting l1 block header for block %d. Error: %v", s.genesis.GenesisBlockNum, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr + } + return err } lastEthBlockSynced = &state.Block{ BlockNumber: header.Number.Uint64(), @@ -89,26 +119,64 @@ func (s *ClientSynchronizer) Sync() error { } newRoot, err := s.state.SetGenesis(s.ctx, *lastEthBlockSynced, s.genesis, dbTx) if err != nil { - log.Fatal("error setting genesis: ", err) + log.Error("error setting genesis: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr + } + return err } var root common.Hash root.SetBytes(newRoot) if root != s.genesis.Root { - log.Fatal("Calculated newRoot should be ", s.genesis.Root, " instead of ", root) + log.Errorf("Calculated newRoot should be %s instead of %s", s.genesis.Root.String(), root.String()) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v", rollbackErr) + return rollbackErr + } + return fmt.Errorf("Calculated newRoot should be %s instead of %s", s.genesis.Root.String(), root.String()) } log.Debug("Genesis root matches!") } else { - log.Fatal("unexpected error getting the latest ethereum block. Error: ", err) + log.Error("unexpected error getting the latest ethereum block. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr + } + return err + } + } + initBatchNumber, err := s.state.GetLastBatchNumber(s.ctx, dbTx) + if err != nil { + log.Error("error getting latest batchNumber synced. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr + } + return err + } + err = s.state.SetInitSyncBatch(s.ctx, initBatchNumber, dbTx) + if err != nil { + log.Error("error setting initial batch number. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr } + return err } if err := dbTx.Commit(s.ctx); err != nil { - log.Errorf("error committing dbTx, err: %s", err.Error()) + log.Errorf("error committing dbTx, err: %v", err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. RollbackErr: %s, err: %s", - rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. RollbackErr: %v, err: %s", rollbackErr, err.Error()) + return rollbackErr } - log.Fatalf("error committing dbTx, err: %s", err.Error()) + return err } for { @@ -116,13 +184,6 @@ func (s *ClientSynchronizer) Sync() error { case <-s.ctx.Done(): return nil case <-time.After(waitDuration): - //Sync L1Blocks - if lastEthBlockSynced, err = s.syncBlocks(lastEthBlockSynced); err != nil { - log.Warn("error syncing blocks: ", err) - if s.ctx.Err() != nil { - continue - } - } latestSequencedBatchNumber, err := s.etherMan.GetLatestBatchNumber() if err != nil { log.Warn("error getting latest sequenced batch in the rollup. Error: ", err) @@ -130,9 +191,22 @@ func (s *ClientSynchronizer) Sync() error { } latestSyncedBatch, err := s.state.GetLastBatchNumber(s.ctx, nil) if err != nil { - log.Warn("error getting latest batch synced. Error: ", err) + log.Warn("error getting latest batch synced in the db. Error: ", err) + continue + } + // Check the latest verified Batch number in the smc + lastVerifiedBatchNumber, err := s.etherMan.GetLatestVerifiedBatchNum() + if err != nil { + log.Warn("error getting last verified batch in the rollup. Error: ", err) + continue + } + err = s.state.SetLastBatchInfoSeenOnEthereum(s.ctx, latestSequencedBatchNumber, lastVerifiedBatchNumber, nil) + if err != nil { + log.Warn("error setting latest batch info into db. Error: ", err) continue } + + // Sync trusted state if latestSyncedBatch >= latestSequencedBatchNumber { log.Info("L1 state fully synchronized") err = s.syncTrustedState(latestSyncedBatch) @@ -140,9 +214,19 @@ func (s *ClientSynchronizer) Sync() error { log.Warn("error syncing trusted state. Error: ", err) continue } - log.Info("Trusted state fully synchronized") waitDuration = s.cfg.SyncInterval.Duration } + //Sync L1Blocks + if lastEthBlockSynced, err = s.syncBlocks(lastEthBlockSynced); err != nil { + log.Warn("error syncing blocks: ", err) + lastEthBlockSynced, err = s.state.GetLastBlock(s.ctx, nil) + if err != nil { + log.Fatal("error getting lastEthBlockSynced to resume the synchronization... Error: ", err) + } + if s.ctx.Err() != nil { + continue + } + } } } } @@ -152,13 +236,13 @@ func (s *ClientSynchronizer) syncBlocks(lastEthBlockSynced *state.Block) (*state // This function will read events fromBlockNum to latestEthBlock. Check reorg to be sure that everything is ok. block, err := s.checkReorg(lastEthBlockSynced) if err != nil { - log.Errorf("error checking reorgs. Retrying... Err: %s", err.Error()) + log.Errorf("error checking reorgs. Retrying... Err: %v", err) return lastEthBlockSynced, fmt.Errorf("error checking reorgs") } if block != nil { err = s.resetState(block.BlockNumber) if err != nil { - log.Errorf("error resetting the state to a previous block. Err: %s, Retrying...", err.Error()) + log.Errorf("error resetting the state to a previous block. Retrying... Err: %v", err) return lastEthBlockSynced, fmt.Errorf("error resetting the state to a previous block") } return block, nil @@ -178,7 +262,7 @@ func (s *ClientSynchronizer) syncBlocks(lastEthBlockSynced *state.Block) (*state for { toBlock := fromBlock + s.cfg.SyncChunkSize - + log.Infof("Syncing block %d of %d", fromBlock, lastKnownBlock.Uint64()) log.Infof("Getting rollup info from block %d to block %d", fromBlock, toBlock) // This function returns the rollup information contained in the ethereum blocks and an extra param called order. // Order param is a map that contains the event order to allow the synchronizer store the info in the same order that is readed. @@ -189,7 +273,10 @@ func (s *ClientSynchronizer) syncBlocks(lastEthBlockSynced *state.Block) (*state if err != nil { return lastEthBlockSynced, err } - s.processBlockRange(blocks, order) + err = s.processBlockRange(blocks, order) + if err != nil { + return lastEthBlockSynced, err + } if len(blocks) > 0 { lastEthBlockSynced = &state.Block{ BlockNumber: blocks[len(blocks)-1].BlockNumber, @@ -219,7 +306,10 @@ func (s *ClientSynchronizer) syncBlocks(lastEthBlockSynced *state.Block) (*state ParentHash: fb.ParentHash(), ReceivedAt: time.Unix(int64(fb.Time()), 0), } - s.processBlockRange([]etherman.Block{b}, order) + err = s.processBlockRange([]etherman.Block{b}, order) + if err != nil { + return lastEthBlockSynced, err + } block := state.Block{ BlockNumber: fb.NumberU64(), BlockHash: fb.Hash(), @@ -242,95 +332,63 @@ func (s *ClientSynchronizer) syncTrustedState(latestSyncedBatch uint64) error { return nil } - log.Debug("Getting broadcast URI") - broadcastURI, err := s.getBroadcastURI() - if err != nil { - log.Errorf("error getting broadcast URI. Error: %v", err) - return err - } - log.Debug("broadcastURI ", broadcastURI) - broadcastClient, _, _ := broadcast.NewClient(s.ctx, broadcastURI) - log.Info("Getting trusted state info") - lastTrustedStateBatch, err := broadcastClient.GetLastBatch(s.ctx, &emptypb.Empty{}) + lastTrustedStateBatchNumber, err := s.zkEVMClient.BatchNumber(s.ctx) if err != nil { log.Warn("error syncing trusted state. Error: ", err) return err } - log.Debug("lastTrustedStateBatch.BatchNumber ", lastTrustedStateBatch.BatchNumber) + log.Debug("lastTrustedStateBatchNumber ", lastTrustedStateBatchNumber) log.Debug("latestSyncedBatch ", latestSyncedBatch) - if lastTrustedStateBatch.BatchNumber < latestSyncedBatch { + if lastTrustedStateBatchNumber < latestSyncedBatch { return nil } batchNumberToSync := latestSyncedBatch - for batchNumberToSync <= lastTrustedStateBatch.BatchNumber { - batchToSync, err := broadcastClient.GetBatch(s.ctx, &pb.GetBatchRequest{BatchNumber: batchNumberToSync}) + for batchNumberToSync <= lastTrustedStateBatchNumber { + batchToSync, err := s.zkEVMClient.BatchByNumber(s.ctx, big.NewInt(0).SetUint64(batchNumberToSync)) if err != nil { - log.Warnf("failed to get batch %v from trusted state via broadcast. Error: %v", batchNumberToSync, err) + log.Warnf("failed to get batch %v from trusted state. Error: %v", batchNumberToSync, err) return err } dbTx, err := s.state.BeginStateTransaction(s.ctx) if err != nil { - log.Fatalf("error creating db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + log.Errorf("error creating db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + return err } if err := s.processTrustedBatch(batchToSync, dbTx); err != nil { log.Errorf("error processing trusted batch %v: %v", batchNumberToSync, err) err := dbTx.Rollback(s.ctx) if err != nil { - log.Fatalf("error rolling back db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + log.Errorf("error rolling back db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + return err } break } if err := dbTx.Commit(s.ctx); err != nil { - log.Fatalf("error committing db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + log.Errorf("error committing db transaction to sync trusted batch %v: %v", batchNumberToSync, err) + return err } batchNumberToSync++ } + log.Info("Trusted state fully synchronized") return nil } -// gets the broadcast URI from trusted sequencer JSON RPC server -func (s *ClientSynchronizer) getBroadcastURI() (string, error) { - log.Debug("getting trusted sequencer URL from smc") - trustedSequencerURL, err := s.etherMan.GetTrustedSequencerURL() - if err != nil { - return "", err - } - log.Debug("trustedSequencerURL ", trustedSequencerURL) - - log.Debug("getting broadcast URI from Trusted Sequencer JSON RPC Server") - res, err := jsonrpc.JSONRPCCall(trustedSequencerURL, "zkevm_getBroadcastURI") - if err != nil { - return "", err - } - - if res.Error != nil { - errMsg := fmt.Sprintf("%v:%v", res.Error.Code, res.Error.Message) - return "", errors.New(errMsg) - } - - var url string - if err := json.Unmarshal(res.Result, &url); err != nil { - return "", err - } - - return url, nil -} - -func (s *ClientSynchronizer) processBlockRange(blocks []etherman.Block, order map[common.Hash][]etherman.Order) { +func (s *ClientSynchronizer) processBlockRange(blocks []etherman.Block, order map[common.Hash][]etherman.Order) error { // New info has to be included into the db using the state for i := range blocks { // Begin db transaction dbTx, err := s.state.BeginStateTransaction(s.ctx) if err != nil { - log.Fatalf("error creating db transaction to store block. BlockNumber: %d, error: %s", blocks[i].BlockNumber, err.Error()) + log.Errorf("error creating db transaction to store block. BlockNumber: %d, error: %v", blocks[i].BlockNumber, err) + return err } b := state.Block{ BlockNumber: blocks[i].BlockNumber, @@ -341,36 +399,60 @@ func (s *ClientSynchronizer) processBlockRange(blocks []etherman.Block, order ma // Add block information err = s.state.AddBlock(s.ctx, &b, dbTx) if err != nil { + log.Errorf("error storing block. BlockNumber: %d, error: %v", blocks[i].BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %s", blocks[i].BlockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blocks[i].BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing block. BlockNumber: %d, error: %s", blocks[i].BlockNumber, err.Error()) + return err } for _, element := range order[blocks[i].BlockHash] { switch element.Name { case etherman.SequenceBatchesOrder: - s.processSequenceBatches(blocks[i].SequencedBatches[element.Pos], blocks[i].BlockNumber, dbTx) + err = s.processSequenceBatches(blocks[i].SequencedBatches[element.Pos], blocks[i].BlockNumber, dbTx) + if err != nil { + return err + } case etherman.ForcedBatchesOrder: - s.processForcedBatch(blocks[i].ForcedBatches[element.Pos], dbTx) + err = s.processForcedBatch(blocks[i].ForcedBatches[element.Pos], dbTx) + if err != nil { + return err + } case etherman.GlobalExitRootsOrder: - s.processGlobalExitRoot(blocks[i].GlobalExitRoots[element.Pos], dbTx) + err = s.processGlobalExitRoot(blocks[i].GlobalExitRoots[element.Pos], dbTx) + if err != nil { + return err + } case etherman.SequenceForceBatchesOrder: - s.processSequenceForceBatch(blocks[i].SequencedForceBatches[element.Pos], blocks[i].BlockNumber, dbTx) - case etherman.VerifyBatchOrder: - s.processVerifiedBatch(blocks[i].VerifiedBatches[element.Pos], dbTx) + err = s.processSequenceForceBatch(blocks[i].SequencedForceBatches[element.Pos], blocks[i], dbTx) + if err != nil { + return err + } + case etherman.TrustedVerifyBatchOrder: + err = s.processTrustedVerifyBatches(blocks[i].VerifiedBatches[element.Pos], dbTx) + if err != nil { + return err + } + case etherman.ForkIDsOrder: + err = s.processForkID(blocks[i].ForkIDs[element.Pos], blocks[i].BlockNumber, dbTx) + if err != nil { + return err + } } } err = dbTx.Commit(s.ctx) if err != nil { - log.Errorf("error committing state to store block. BlockNumber: %d, err: %s", blocks[i].BlockNumber, err.Error()) + log.Errorf("error committing state to store block. BlockNumber: %d, err: %v", blocks[i].BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %s", blocks[i].BlockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blocks[i].BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error committing state to store block. BlockNumber: %d, err: %s", blocks[i].BlockNumber, err.Error()) + return err } } + return nil } // This function allows reset the state until an specific ethereum block @@ -385,17 +467,27 @@ func (s *ClientSynchronizer) resetState(blockNumber uint64) error { if err != nil { rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) return rollbackErr } log.Error("error resetting the state. Error: ", err) return err } + err = s.ethTxManager.Reorg(s.ctx, blockNumber+1, dbTx) + if err != nil { + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back eth tx manager when reorg detected. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + log.Error("error processing reorg on eth tx manager. Error: ", err) + return err + } err = dbTx.Commit(s.ctx) if err != nil { rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) return rollbackErr } log.Error("error committing the resetted state. Error: ", err) @@ -420,17 +512,17 @@ func (s *ClientSynchronizer) checkReorg(latestBlock *state.Block) (*state.Block, for { block, err := s.etherMan.EthBlockByNumber(s.ctx, latestBlock.BlockNumber) if err != nil { - log.Errorf("error getting latest block synced from blockchain. Block: %d, error: %s", latestBlock.BlockNumber, err.Error()) + log.Errorf("error getting latest block synced from blockchain. Block: %d, error: %v", latestBlock.BlockNumber, err) return nil, err } if block.NumberU64() != latestBlock.BlockNumber { - err = fmt.Errorf("Wrong ethereum block retrieved from blockchain. Block numbers don't match. BlockNumber stored: %d. BlockNumber retrieved: %d", + err = fmt.Errorf("wrong ethereum block retrieved from blockchain. Block numbers don't match. BlockNumber stored: %d. BlockNumber retrieved: %d", latestBlock.BlockNumber, block.NumberU64()) log.Error("error: ", err) return nil, err } // Compare hashes - if (block.Hash() != latestBlock.BlockHash || block.ParentHash() != latestBlock.ParentHash) && latestBlock.BlockNumber > s.genBlockNumber { + if (block.Hash() != latestBlock.BlockHash || block.ParentHash() != latestBlock.ParentHash) && latestBlock.BlockNumber > s.genesis.GenesisBlockNum { log.Debug("[checkReorg function] => latestBlockNumber: ", latestBlock.BlockNumber) log.Debug("[checkReorg function] => latestBlockHash: ", latestBlock.BlockHash) log.Debug("[checkReorg function] => latestBlockHashParent: ", latestBlock.ParentHash) @@ -442,18 +534,20 @@ func (s *ClientSynchronizer) checkReorg(latestBlock *state.Block) (*state.Block, // Reorg detected. Getting previous block dbTx, err := s.state.BeginStateTransaction(s.ctx) if err != nil { - log.Fatalf("error creating db transaction to get prevoius blocks") + log.Errorf("error creating db transaction to get prevoius blocks") + return nil, err } latestBlock, err = s.state.GetPreviousBlock(s.ctx, depth, dbTx) errC := dbTx.Commit(s.ctx) if errC != nil { - log.Errorf("error committing dbTx, err: %s", errC.Error()) + log.Errorf("error committing dbTx, err: %v", errC) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. RollbackErr: %s, err: %s", - rollbackErr.Error(), errC.Error()) + log.Errorf("error rolling back state. RollbackErr: %v", rollbackErr) + return nil, rollbackErr } - log.Fatalf("error committing dbTx, err: %s", errC.Error()) + log.Errorf("error committing dbTx, err: %v", errC) + return nil, errC } if errors.Is(err, state.ErrNotFound) { log.Warn("error checking reorg: previous block not found in db: ", err) @@ -477,246 +571,465 @@ func (s *ClientSynchronizer) Stop() { s.cancelCtx() } -func (s *ClientSynchronizer) checkTrustedState(batch state.Batch, dbTx pgx.Tx) (bool, error) { - // First get trusted batch from db - tBatch, err := s.state.GetBatchByNumber(s.ctx, batch.BatchNumber, dbTx) +func (s *ClientSynchronizer) checkTrustedState(batch state.Batch, tBatch *state.Batch, newRoot common.Hash, dbTx pgx.Tx) bool { + //Compare virtual state with trusted state + var reorgReasons strings.Builder + if newRoot != tBatch.StateRoot { + log.Warnf("Different field StateRoot. Virtual: %s, Trusted: %s\n", newRoot.String(), tBatch.StateRoot.String()) + reorgReasons.WriteString(fmt.Sprintf("Different field StateRoot. Virtual: %s, Trusted: %s\n", newRoot.String(), tBatch.StateRoot.String())) + } + if hex.EncodeToString(batch.BatchL2Data) != hex.EncodeToString(tBatch.BatchL2Data) { + log.Warnf("Different field BatchL2Data. Virtual: %s, Trusted: %s\n", hex.EncodeToString(batch.BatchL2Data), hex.EncodeToString(tBatch.BatchL2Data)) + reorgReasons.WriteString(fmt.Sprintf("Different field BatchL2Data. Virtual: %s, Trusted: %s\n", hex.EncodeToString(batch.BatchL2Data), hex.EncodeToString(tBatch.BatchL2Data))) + } + if batch.GlobalExitRoot.String() != tBatch.GlobalExitRoot.String() { + log.Warnf("Different field GlobalExitRoot. Virtual: %s, Trusted: %s\n", batch.GlobalExitRoot.String(), tBatch.GlobalExitRoot.String()) + reorgReasons.WriteString(fmt.Sprintf("Different field GlobalExitRoot. Virtual: %s, Trusted: %s\n", batch.GlobalExitRoot.String(), tBatch.GlobalExitRoot.String())) + } + if batch.Timestamp.Unix() != tBatch.Timestamp.Unix() { + log.Warnf("Different field Timestamp. Virtual: %d, Trusted: %d\n", batch.Timestamp.Unix(), tBatch.Timestamp.Unix()) + reorgReasons.WriteString(fmt.Sprintf("Different field Timestamp. Virtual: %d, Trusted: %d\n", batch.Timestamp.Unix(), tBatch.Timestamp.Unix())) + } + if batch.Coinbase.String() != tBatch.Coinbase.String() { + log.Warnf("Different field Coinbase. Virtual: %s, Trusted: %s\n", batch.Coinbase.String(), tBatch.Coinbase.String()) + reorgReasons.WriteString(fmt.Sprintf("Different field Coinbase. Virtual: %s, Trusted: %s\n", batch.Coinbase.String(), tBatch.Coinbase.String())) + } + + if reorgReasons.Len() > 0 { + reason := reorgReasons.String() + log.Warnf("Trusted Reorg detected for Batch Number: %d. Reasons: %s", tBatch.BatchNumber, reason) + if s.isTrustedSequencer { + for { + log.Error("TRUSTED REORG DETECTED! Batch: ", batch.BatchNumber) + time.Sleep(5 * time.Second) //nolint:gomnd + } + } + // Store trusted reorg register + tr := state.TrustedReorg{ + BatchNumber: tBatch.BatchNumber, + Reason: reason, + } + err := s.state.AddTrustedReorg(s.ctx, &tr, dbTx) + if err != nil { + log.Error("error storing tursted reorg register into the db. Error: ", err) + } + return true + } + return false +} + +func (s *ClientSynchronizer) processForkID(forkID etherman.ForkID, blockNumber uint64, dbTx pgx.Tx) error { + //If the forkID.batchnumber is a future batch + latestBatchNumber, err := s.state.GetLastBatchNumber(s.ctx, dbTx) if err != nil { - return false, err + log.Error("error getting last batch number. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err } - //Compare virtual state with trusted state - if hex.EncodeToString(batch.BatchL2Data) == hex.EncodeToString(tBatch.BatchL2Data) && - batch.GlobalExitRoot.String() == tBatch.GlobalExitRoot.String() && - batch.Timestamp.Unix() == tBatch.Timestamp.Unix() && - batch.Coinbase.String() == tBatch.Coinbase.String() { - return true, nil + if latestBatchNumber < forkID.BatchNumber { //If the forkID will start in a future batch + // Read Fork ID FROM POE SC + forkIDIntervals, err := s.etherMan.GetForks(s.ctx, s.genesis.GenesisBlockNum) + if err != nil || len(forkIDIntervals) == 0 { + log.Error("error getting all forkIDs: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err + } + // Update forkID intervals in the state + s.state.UpdateForkIDIntervals(forkIDIntervals) + return nil + } + + // If forkID affects to a batch from the past. State must be reseted. + log.Debugf("ForkID: %d, Reverting synchronization to batch: %d", forkID.ForkID, forkID.BatchNumber+1) + count, err := s.state.GetForkIDTrustedReorgCount(s.ctx, forkID.ForkID, forkID.Version, dbTx) + if err != nil { + log.Error("error getting ForkIDTrustedReorg. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state get forkID trusted state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err + } + if count > 0 { // If the forkID reset was already done + return nil + } + + // Read Fork ID FROM POE SC + forkIDIntervals, err := s.etherMan.GetForks(s.ctx, s.genesis.GenesisBlockNum) + if err != nil || len(forkIDIntervals) == 0 { + log.Error("error getting all forkIDs: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err + } + + //Reset DB + err = s.state.ResetForkID(s.ctx, forkID.BatchNumber+1, forkID.ForkID, forkID.Version, dbTx) + if err != nil { + log.Error("error resetting the state. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err + } + err = dbTx.Commit(s.ctx) + if err != nil { + log.Error("error committing the resetted state. Error: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state to store block. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err } - return false, nil + + // Update forkID intervals in the state + s.state.UpdateForkIDIntervals(forkIDIntervals) + + return fmt.Errorf("new ForkID detected, reseting synchronizarion") } -func (s *ClientSynchronizer) processSequenceBatches(sequencedBatches []etherman.SequencedBatch, blockNumber uint64, dbTx pgx.Tx) { +func (s *ClientSynchronizer) processSequenceBatches(sequencedBatches []etherman.SequencedBatch, blockNumber uint64, dbTx pgx.Tx) error { + if len(sequencedBatches) == 0 { + log.Warn("Empty sequencedBatches array detected, ignoring...") + return nil + } for _, sbatch := range sequencedBatches { - vb := state.VirtualBatch{ - BatchNumber: sbatch.BatchNumber, - TxHash: sbatch.TxHash, - Coinbase: sbatch.Coinbase, - BlockNumber: blockNumber, - } - virtualBatches := []state.VirtualBatch{vb} - b := state.Batch{ + virtualBatch := state.VirtualBatch{ + BatchNumber: sbatch.BatchNumber, + TxHash: sbatch.TxHash, + Coinbase: sbatch.Coinbase, + BlockNumber: blockNumber, + SequencerAddr: sbatch.SequencerAddr, + } + batch := state.Batch{ BatchNumber: sbatch.BatchNumber, GlobalExitRoot: sbatch.GlobalExitRoot, Timestamp: time.Unix(int64(sbatch.Timestamp), 0), Coinbase: sbatch.Coinbase, BatchL2Data: sbatch.Transactions, } - batches := []state.Batch{b} - // ForcedBatches must be processed after the batch. - numForcedBatches := len(sbatch.ForceBatchesTimestamp) - if numForcedBatches > 0 { + // ForcedBatch must be processed + if sbatch.MinForcedTimestamp > 0 { // If this is true means that the batch is forced + log.Debug("FORCED BATCH SEQUENCED!") // Read forcedBatches from db - forcedBatches, err := s.state.GetNextForcedBatches(s.ctx, numForcedBatches, dbTx) + forcedBatches, err := s.state.GetNextForcedBatches(s.ctx, 1, dbTx) if err != nil { - log.Errorf("error getting forcedBatches. BatchNumber: %d", vb.BatchNumber) + log.Errorf("error getting forcedBatches. BatchNumber: %d", virtualBatch.BatchNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", vb.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", virtualBatch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error getting forcedBatches. BatchNumber: %d, BlockNumber: %d, error: %s", vb.BatchNumber, blockNumber, err.Error()) + return err } - if numForcedBatches != len(forcedBatches) { + if len(forcedBatches) == 0 { + log.Errorf("error: empty forcedBatches array read from db. BatchNumber: %d", sbatch.BatchNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s", vb.BatchNumber, blockNumber, rollbackErr.Error()) - } - log.Fatal("error number of forced batches doesn't match") - } - for i, forcedBatch := range forcedBatches { - vb := state.VirtualBatch{ - BatchNumber: sbatch.BatchNumber + uint64(i), - TxHash: sbatch.TxHash, - Coinbase: sbatch.Coinbase, - BlockNumber: blockNumber, + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %v", sbatch.BatchNumber, blockNumber, rollbackErr) + return rollbackErr } - virtualBatches = append(virtualBatches, vb) - tb := state.Batch{ - BatchNumber: sbatch.BatchNumber + uint64(i), // First process the batch and then the forcedBatches - GlobalExitRoot: forcedBatch.GlobalExitRoot, - Timestamp: time.Unix(int64(sbatch.ForceBatchesTimestamp[i]), 0), // ForceBatchesTimestamp instead of forcedAt because it is the timestamp selected by the sequencer, not when the forced batch was sent. This forcedAt is the min timestamp allowed. - Coinbase: forcedBatch.Sequencer, - BatchL2Data: forcedBatch.RawTxsData, + return fmt.Errorf("error: empty forcedBatches array read from db. BatchNumber: %d", sbatch.BatchNumber) + } + if uint64(forcedBatches[0].ForcedAt.Unix()) != sbatch.MinForcedTimestamp || + forcedBatches[0].GlobalExitRoot != sbatch.GlobalExitRoot || + common.Bytes2Hex(forcedBatches[0].RawTxsData) != common.Bytes2Hex(sbatch.Transactions) { + log.Warnf("ForcedBatch stored: %+v", forcedBatches) + log.Warnf("ForcedBatch sequenced received: %+v", sbatch) + log.Errorf("error: forcedBatch received doesn't match with the next expected forcedBatch stored in db. Expected: %+v, Synced: %+v", forcedBatches, sbatch) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %v", virtualBatch.BatchNumber, blockNumber, rollbackErr) + return rollbackErr } - batches = append(batches, tb) - // Store batchNumber in forced_batch table - err = s.state.AddBatchNumberInForcedBatch(s.ctx, forcedBatch.ForcedBatchNumber, tb.BatchNumber, dbTx) + return fmt.Errorf("error: forcedBatch received doesn't match with the next expected forcedBatch stored in db. Expected: %+v, Synced: %+v", forcedBatches, sbatch) + } + batch.ForcedBatchNum = &forcedBatches[0].ForcedBatchNumber + } + + // Now we need to check the batch. ForcedBatches should be already stored in the batch table because this is done by the sequencer + processCtx := state.ProcessingContext{ + BatchNumber: batch.BatchNumber, + Coinbase: batch.Coinbase, + Timestamp: batch.Timestamp, + GlobalExitRoot: batch.GlobalExitRoot, + ForcedBatchNum: batch.ForcedBatchNum, + } + + var newRoot common.Hash + + // First get trusted batch from db + tBatch, err := s.state.GetBatchByNumber(s.ctx, batch.BatchNumber, dbTx) + if err != nil { + if errors.Is(err, state.ErrNotFound) || errors.Is(err, state.ErrStateNotSynchronized) { + log.Debugf("BatchNumber: %d, not found in trusted state. Storing it...", batch.BatchNumber) + // If it is not found, store batch + newStateRoot, err := s.state.ProcessAndStoreClosedBatch(s.ctx, processCtx, batch.BatchL2Data, dbTx, metrics.SynchronizerCallerLabel) if err != nil { - log.Errorf("error adding the batchNumber to forcedBatch in processSequenceBatches. BlockNumber: %d", blockNumber) + log.Errorf("error storing trustedBatch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", batch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error adding the batchNumber to forcedBatch in processSequenceBatches. BlockNumber: %d, error: %s", blockNumber, err.Error()) + log.Errorf("error storing batch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) + return err + } + newRoot = newStateRoot + tBatch = &batch + tBatch.StateRoot = newRoot + } else { + log.Error("error checking trusted state: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %v", batch.BatchNumber, blockNumber, rollbackErr) + return rollbackErr } + return err } - } + } else { + // Reprocess batch to compare the stateRoot with tBatch.StateRoot and get accInputHash + p, err := s.state.ExecuteBatch(s.ctx, batch, false, dbTx) + if err != nil { + log.Errorf("error executing L1 batch: %+v, error: %v", batch, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", batch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr + } + return err + } + newRoot = common.BytesToHash(p.NewStateRoot) + accumulatedInputHash := common.BytesToHash(p.NewAccInputHash) - if len(virtualBatches) != len(batches) { - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s", vb.BatchNumber, blockNumber, rollbackErr.Error()) + //AddAccumulatedInputHash + err = s.state.AddAccumulatedInputHash(s.ctx, batch.BatchNumber, accumulatedInputHash, dbTx) + if err != nil { + log.Errorf("error adding accumulatedInputHash for batch: %d. Error; %v", batch.BatchNumber, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %v", batch.BatchNumber, blockNumber, rollbackErr) + return rollbackErr + } + return err } - log.Fatal("error: length of batches and virtualBatches don't match.\nvirtualBatches: %+v \nbatches: %+v", virtualBatches, batches) } - // Now we need to check all the batches. ForcedBatches should be already stored in the batch table because this is done by the sequencer - for i, batch := range batches { - processCtx := state.ProcessingContext{ - BatchNumber: batch.BatchNumber, - Coinbase: batch.Coinbase, - Timestamp: batch.Timestamp, - GlobalExitRoot: batch.GlobalExitRoot, - } - // Call the check trusted state method to compare trusted and virtual state - status, err := s.checkTrustedState(batch, dbTx) + // Call the check trusted state method to compare trusted and virtual state + status := s.checkTrustedState(batch, tBatch, newRoot, dbTx) + if status { + // Reorg Pool + err := s.reorgPool(dbTx) if err != nil { - if errors.Is(err, state.ErrNotFound) || errors.Is(err, state.ErrStateNotSynchronized) { - log.Debugf("BatchNumber: %d, not found in trusted state. Storing it...", batch.BatchNumber) - // If it is not found, store batch - err = s.state.ProcessAndStoreClosedBatch(s.ctx, processCtx, batch.BatchL2Data, dbTx) - if err != nil { - log.Errorf("error storing trustedBatch. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", batch.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) - } - log.Fatalf("error storing batch. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) - } - status = true - } else { - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", vb.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) - } - log.Fatal("error checking trusted state: ", err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", tBatch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } + log.Errorf("error: %v. BatchNumber: %d, BlockNumber: %d", err, tBatch.BatchNumber, blockNumber) + return err } - if !status { - // Reset trusted state - previousBatchNumber := batch.BatchNumber - 1 - log.Infof("Trusted reorg detected, discarding batches until batchNum %d", previousBatchNumber) - err := s.state.ResetTrustedState(s.ctx, previousBatchNumber, dbTx) // This method has to reset the forced batches deleting the batchNumber for higher batchNumbers - if err != nil { - log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", batch.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) - } - log.Fatalf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) - } - err = s.state.ProcessAndStoreClosedBatch(s.ctx, processCtx, batch.BatchL2Data, dbTx) - if err != nil { - log.Errorf("error storing trustedBatch. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", batch.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) - } - log.Fatalf("error storing batch. BatchNumber: %d, BlockNumber: %d, error: %s", batch.BatchNumber, blockNumber, err.Error()) + + // Reset trusted state + previousBatchNumber := batch.BatchNumber - 1 + log.Warnf("Trusted reorg detected, discarding batches until batchNum %d", previousBatchNumber) + err = s.state.ResetTrustedState(s.ctx, previousBatchNumber, dbTx) // This method has to reset the forced batches deleting the batchNumber for higher batchNumbers + if err != nil { + log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", batch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } + log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) + return err } - // Store virtualBatch - err = s.state.AddVirtualBatch(s.ctx, &virtualBatches[i], dbTx) + _, err = s.state.ProcessAndStoreClosedBatch(s.ctx, processCtx, batch.BatchL2Data, dbTx, metrics.SynchronizerCallerLabel) if err != nil { - log.Errorf("error storing virtualBatch. BatchNumber: %d, BlockNumber: %d, error: %s", virtualBatches[i].BatchNumber, blockNumber, err.Error()) + log.Errorf("error storing trustedBatch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", virtualBatches[i].BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", batch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing virtualBatch. BatchNumber: %d, BlockNumber: %d, error: %s", virtualBatches[i].BatchNumber, blockNumber, err.Error()) + log.Errorf("error storing batch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, blockNumber, err) + return err + } + } + + // Store virtualBatch + err = s.state.AddVirtualBatch(s.ctx, &virtualBatch, dbTx) + if err != nil { + log.Errorf("error storing virtualBatch. BatchNumber: %d, BlockNumber: %d, error: %v", virtualBatch.BatchNumber, blockNumber, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", virtualBatch.BatchNumber, blockNumber, rollbackErr.Error(), err) + return rollbackErr } + log.Errorf("error storing virtualBatch. BatchNumber: %d, BlockNumber: %d, error: %v", virtualBatch.BatchNumber, blockNumber, err) + return err + } + } + // Insert the sequence to allow the aggregator verify the sequence batches + seq := state.Sequence{ + FromBatchNumber: sequencedBatches[0].BatchNumber, + ToBatchNumber: sequencedBatches[len(sequencedBatches)-1].BatchNumber, + } + err := s.state.AddSequence(s.ctx, seq, dbTx) + if err != nil { + log.Errorf("error adding sequence. Sequence: %+v", seq) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err) + return rollbackErr } + log.Errorf("error getting adding sequence. BlockNumber: %d, error: %v", blockNumber, err) + return err } + return nil } -func (s *ClientSynchronizer) processSequenceForceBatch(sequenceForceBatch etherman.SequencedForceBatch, blockNumber uint64, dbTx pgx.Tx) { - // First, reset trusted state - lastVirtualizedBatchNumber := sequenceForceBatch.LastBatchSequenced - sequenceForceBatch.ForceBatchNumber - err := s.state.ResetTrustedState(s.ctx, lastVirtualizedBatchNumber, dbTx) // This method has to reset the forced batches deleting the batchNumber for higher batchNumbers +func (s *ClientSynchronizer) processSequenceForceBatch(sequenceForceBatch []etherman.SequencedForceBatch, block etherman.Block, dbTx pgx.Tx) error { + if len(sequenceForceBatch) == 0 { + log.Warn("Empty sequenceForceBatch array detected, ignoring...") + return nil + } + // First, get last virtual batch number + lastVirtualizedBatchNumber, err := s.state.GetLastVirtualBatchNum(s.ctx, dbTx) + if err != nil { + log.Errorf("error getting lastVirtualBatchNumber. BlockNumber: %d, error: %v", block.BlockNumber, err) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", lastVirtualizedBatchNumber, block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr + } + log.Errorf("error getting lastVirtualBatchNumber. BlockNumber: %d, error: %v", block.BlockNumber, err) + return err + } + // Second, reset trusted state + err = s.state.ResetTrustedState(s.ctx, lastVirtualizedBatchNumber, dbTx) // This method has to reset the forced batches deleting the batchNumber for higher batchNumbers if err != nil { - log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %s", lastVirtualizedBatchNumber, blockNumber, err.Error()) + log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %v", lastVirtualizedBatchNumber, block.BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", lastVirtualizedBatchNumber, blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", lastVirtualizedBatchNumber, block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %s", lastVirtualizedBatchNumber, blockNumber, err.Error()) + log.Errorf("error resetting trusted state. BatchNumber: %d, BlockNumber: %d, error: %v", lastVirtualizedBatchNumber, block.BlockNumber, err) + return err } // Read forcedBatches from db - forcedBatches, err := s.state.GetNextForcedBatches(s.ctx, int(sequenceForceBatch.ForceBatchNumber), dbTx) + forcedBatches, err := s.state.GetNextForcedBatches(s.ctx, len(sequenceForceBatch), dbTx) if err != nil { - log.Errorf("error getting forcedBatches in processSequenceForceBatch. BlockNumber: %d", blockNumber) + log.Errorf("error getting forcedBatches in processSequenceForceBatch. BlockNumber: %d", block.BlockNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error getting forcedBatches in processSequenceForceBatch. BlockNumber: %d, error: %s", blockNumber, err.Error()) + log.Errorf("error getting forcedBatches in processSequenceForceBatch. BlockNumber: %d, error: %v", block.BlockNumber, err) + return err } - if int(sequenceForceBatch.ForceBatchNumber) != len(forcedBatches) { + if len(sequenceForceBatch) != len(forcedBatches) { rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %v", block.BlockNumber, rollbackErr) + return rollbackErr } - log.Fatal("error number of forced batches doesn't match") + log.Error("error number of forced batches doesn't match") + return fmt.Errorf("error number of forced batches doesn't match") } - - for i, fbatch := range forcedBatches { - vb := state.VirtualBatch{ - BatchNumber: sequenceForceBatch.LastBatchSequenced - sequenceForceBatch.ForceBatchNumber + uint64(i), - TxHash: sequenceForceBatch.TxHash, - Coinbase: sequenceForceBatch.Coinbase, - BlockNumber: blockNumber, + for i, fbatch := range sequenceForceBatch { + if uint64(forcedBatches[i].ForcedAt.Unix()) != fbatch.MinForcedTimestamp || + forcedBatches[i].GlobalExitRoot != fbatch.GlobalExitRoot || + common.Bytes2Hex(forcedBatches[i].RawTxsData) != common.Bytes2Hex(fbatch.Transactions) { + log.Warnf("ForcedBatch stored: %+v", forcedBatches) + log.Warnf("ForcedBatch sequenced received: %+v", fbatch) + log.Errorf("error: forcedBatch received doesn't match with the next expected forcedBatch stored in db. Expected: %+v, Synced: %+v", forcedBatches[i], fbatch) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %v", fbatch.BatchNumber, block.BlockNumber, rollbackErr) + return rollbackErr + } + return fmt.Errorf("error: forcedBatch received doesn't match with the next expected forcedBatch stored in db. Expected: %+v, Synced: %+v", forcedBatches[i], fbatch) + } + virtualBatch := state.VirtualBatch{ + BatchNumber: fbatch.BatchNumber, + TxHash: fbatch.TxHash, + Coinbase: fbatch.Coinbase, + SequencerAddr: fbatch.Coinbase, + BlockNumber: block.BlockNumber, } - b := state.ProcessingContext{ - BatchNumber: sequenceForceBatch.LastBatchSequenced - sequenceForceBatch.ForceBatchNumber + uint64(i), + batch := state.ProcessingContext{ + BatchNumber: fbatch.BatchNumber, GlobalExitRoot: fbatch.GlobalExitRoot, - Timestamp: fbatch.ForcedAt, - Coinbase: fbatch.Sequencer, + Timestamp: block.ReceivedAt, + Coinbase: fbatch.Coinbase, + ForcedBatchNum: &forcedBatches[i].ForcedBatchNumber, } // Process batch - err := s.state.ProcessAndStoreClosedBatch(s.ctx, b, fbatch.RawTxsData, dbTx) + _, err := s.state.ProcessAndStoreClosedBatch(s.ctx, batch, forcedBatches[i].RawTxsData, dbTx, metrics.SynchronizerCallerLabel) if err != nil { - log.Errorf("error processing batch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %s", b.BatchNumber, blockNumber, err.Error()) + log.Errorf("error processing batch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, block.BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", b.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", batch.BatchNumber, block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error processing batch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %s", b.BatchNumber, blockNumber, err.Error()) + log.Errorf("error processing batch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %v", batch.BatchNumber, block.BlockNumber, err) + return err } // Store virtualBatch - err = s.state.AddVirtualBatch(s.ctx, &vb, dbTx) + err = s.state.AddVirtualBatch(s.ctx, &virtualBatch, dbTx) if err != nil { - log.Errorf("error storing virtualBatch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %s", vb.BatchNumber, blockNumber, err.Error()) + log.Errorf("error storing virtualBatch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %v", virtualBatch.BatchNumber, block.BlockNumber, err) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %s", vb.BatchNumber, blockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BatchNumber: %d, BlockNumber: %d, rollbackErr: %s, error : %v", virtualBatch.BatchNumber, block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing virtualBatch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %s", vb.BatchNumber, blockNumber, err.Error()) + log.Errorf("error storing virtualBatch in processSequenceForceBatch. BatchNumber: %d, BlockNumber: %d, error: %v", virtualBatch.BatchNumber, block.BlockNumber, err) + return err } - // Store batchNumber in forced_batch table - err = s.state.AddBatchNumberInForcedBatch(s.ctx, fbatch.ForcedBatchNumber, vb.BatchNumber, dbTx) - if err != nil { - log.Errorf("error adding the batchNumber to forcedBatch in processSequenceForceBatch. BlockNumber: %d", blockNumber) - rollbackErr := dbTx.Rollback(s.ctx) - if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", blockNumber, rollbackErr.Error(), err.Error()) - } - log.Fatalf("error adding the batchNumber to forcedBatch in processSequenceForceBatch. BlockNumber: %d, error: %s", blockNumber, err.Error()) + } + // Insert the sequence to allow the aggregator verify the sequence batches + seq := state.Sequence{ + FromBatchNumber: sequenceForceBatch[0].BatchNumber, + ToBatchNumber: sequenceForceBatch[len(sequenceForceBatch)-1].BatchNumber, + } + err = s.state.AddSequence(s.ctx, seq, dbTx) + if err != nil { + log.Errorf("error adding sequence. Sequence: %+v", seq) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", block.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } + log.Errorf("error getting adding sequence. BlockNumber: %d, error: %v", block.BlockNumber, err) + return err } + return nil } -func (s *ClientSynchronizer) processForcedBatch(forcedBatch etherman.ForcedBatch, dbTx pgx.Tx) { +func (s *ClientSynchronizer) processForcedBatch(forcedBatch etherman.ForcedBatch, dbTx pgx.Tx) error { // Store forced batch into the db forcedB := state.ForcedBatch{ BlockNumber: forcedBatch.BlockNumber, - BatchNumber: nil, ForcedBatchNumber: forcedBatch.ForcedBatchNumber, Sequencer: forcedBatch.Sequencer, GlobalExitRoot: forcedBatch.GlobalExitRoot, @@ -728,58 +1041,106 @@ func (s *ClientSynchronizer) processForcedBatch(forcedBatch etherman.ForcedBatch log.Errorf("error storing the forcedBatch in processForcedBatch. BlockNumber: %d", forcedBatch.BlockNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", forcedBatch.BlockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", forcedBatch.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing the forcedBatch in processForcedBatch. BlockNumber: %d, error: %s", forcedBatch.BlockNumber, err.Error()) + log.Errorf("error storing the forcedBatch in processForcedBatch. BlockNumber: %d, error: %v", forcedBatch.BlockNumber, err) + return err } + return nil } -func (s *ClientSynchronizer) processGlobalExitRoot(globalExitRoot etherman.GlobalExitRoot, dbTx pgx.Tx) { +func (s *ClientSynchronizer) processGlobalExitRoot(globalExitRoot etherman.GlobalExitRoot, dbTx pgx.Tx) error { // Store GlobalExitRoot ger := state.GlobalExitRoot{ - BlockNumber: globalExitRoot.BlockNumber, - GlobalExitRootNum: globalExitRoot.GlobalExitRootNum, - MainnetExitRoot: globalExitRoot.MainnetExitRoot, - RollupExitRoot: globalExitRoot.RollupExitRoot, - GlobalExitRoot: globalExitRoot.GlobalExitRoot, + BlockNumber: globalExitRoot.BlockNumber, + MainnetExitRoot: globalExitRoot.MainnetExitRoot, + RollupExitRoot: globalExitRoot.RollupExitRoot, + GlobalExitRoot: globalExitRoot.GlobalExitRoot, } err := s.state.AddGlobalExitRoot(s.ctx, &ger, dbTx) if err != nil { - log.Errorf("error storing the GlobalExitRoot in processGlobalExitRoot. BlockNumber: %d", globalExitRoot.BlockNumber) + log.Errorf("error storing the globalExitRoot in processGlobalExitRoot. BlockNumber: %d", globalExitRoot.BlockNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", globalExitRoot.BlockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", globalExitRoot.BlockNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing the GlobalExitRoot in processGlobalExitRoot. BlockNumber: %d, error: %s", globalExitRoot.BlockNumber, err.Error()) + log.Errorf("error storing the GlobalExitRoot in processGlobalExitRoot. BlockNumber: %d, error: %v", globalExitRoot.BlockNumber, err) + return err } + return nil } -func (s *ClientSynchronizer) processVerifiedBatch(verifiedBatch etherman.VerifiedBatch, dbTx pgx.Tx) { - verifiedB := state.VerifiedBatch{ - BlockNumber: verifiedBatch.BlockNumber, - BatchNumber: verifiedBatch.BatchNumber, - Aggregator: verifiedBatch.Aggregator, - TxHash: verifiedBatch.TxHash, +func (s *ClientSynchronizer) processTrustedVerifyBatches(lastVerifiedBatch etherman.VerifiedBatch, dbTx pgx.Tx) error { + lastVBatch, err := s.state.GetLastVerifiedBatch(s.ctx, dbTx) + if err != nil { + log.Errorf("error getting lastVerifiedBatch stored in db in processTrustedVerifyBatches. Processing synced blockNumber: %d", lastVerifiedBatch.BlockNumber) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. Processing synced blockNumber: %d, rollbackErr: %s, error : %v", lastVerifiedBatch.BlockNumber, rollbackErr.Error(), err) + return rollbackErr + } + log.Errorf("error getting lastVerifiedBatch stored in db in processTrustedVerifyBatches. Processing synced blockNumber: %d, error: %v", lastVerifiedBatch.BlockNumber, err) + return err } - err := s.state.AddVerifiedBatch(s.ctx, &verifiedB, dbTx) + nbatches := lastVerifiedBatch.BatchNumber - lastVBatch.BatchNumber + batch, err := s.state.GetBatchByNumber(s.ctx, lastVerifiedBatch.BatchNumber, dbTx) if err != nil { - log.Errorf("error storing the verifiedBatch in processVerifiedBatch. BlockNumber: %d", verifiedBatch.BlockNumber) + log.Errorf("error getting GetBatchByNumber stored in db in processTrustedVerifyBatches. Processing blockNumber: %d", lastVerifiedBatch.BatchNumber) rollbackErr := dbTx.Rollback(s.ctx) if rollbackErr != nil { - log.Fatalf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %s", verifiedBatch.BlockNumber, rollbackErr.Error(), err.Error()) + log.Errorf("error rolling back state. Processing blockNumber: %d, rollbackErr: %s, error : %v", lastVerifiedBatch.BatchNumber, rollbackErr.Error(), err) + return rollbackErr } - log.Fatalf("error storing the verifiedBatch in processVerifiedBatch. BlockNumber: %d, error: %s", verifiedBatch.BlockNumber, err.Error()) + log.Errorf("error getting GetBatchByNumber stored in db in processTrustedVerifyBatches. Processing blockNumber: %d, error: %v", lastVerifiedBatch.BatchNumber, err) + return err } -} -func (s *ClientSynchronizer) processTrustedBatch(trustedBatch *pb.GetBatchResponse, dbTx pgx.Tx) error { - log.Debugf("processing trusted batch: %v", trustedBatch.BatchNumber) - txs := []types.Transaction{} - for _, transaction := range trustedBatch.Transactions { - tx, err := state.DecodeTx(transaction.Encoded) + // Checks that calculated state root matches with the verified state root in the smc + if batch.StateRoot != lastVerifiedBatch.StateRoot { + log.Warn("nbatches: ", nbatches) + log.Warnf("Batch from db: %+v", batch) + log.Warnf("Verified Batch: %+v", lastVerifiedBatch) + log.Errorf("error: stateRoot calculated and state root verified don't match in processTrustedVerifyBatches. Processing blockNumber: %d", lastVerifiedBatch.BatchNumber) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. Processing blockNumber: %d, rollbackErr: %v", lastVerifiedBatch.BatchNumber, rollbackErr) + return rollbackErr + } + log.Errorf("error: stateRoot calculated and state root verified don't match in processTrustedVerifyBatches. Processing blockNumber: %d", lastVerifiedBatch.BatchNumber) + return fmt.Errorf("error: stateRoot calculated and state root verified don't match in processTrustedVerifyBatches. Processing blockNumber: %d", lastVerifiedBatch.BatchNumber) + } + var i uint64 + for i = 1; i <= nbatches; i++ { + verifiedB := state.VerifiedBatch{ + BlockNumber: lastVerifiedBatch.BlockNumber, + BatchNumber: lastVBatch.BatchNumber + i, + Aggregator: lastVerifiedBatch.Aggregator, + StateRoot: lastVerifiedBatch.StateRoot, + TxHash: lastVerifiedBatch.TxHash, + IsTrusted: true, + } + err = s.state.AddVerifiedBatch(s.ctx, &verifiedB, dbTx) if err != nil { + log.Errorf("error storing the verifiedB in processTrustedVerifyBatches. verifiedBatch: %+v, lastVerifiedBatch: %+v", verifiedB, lastVerifiedBatch) + rollbackErr := dbTx.Rollback(s.ctx) + if rollbackErr != nil { + log.Errorf("error rolling back state. BlockNumber: %d, rollbackErr: %s, error : %v", lastVerifiedBatch.BlockNumber, rollbackErr.Error(), err) + return rollbackErr + } + log.Errorf("error storing the verifiedB in processTrustedVerifyBatches. BlockNumber: %d, error: %v", lastVerifiedBatch.BlockNumber, err) return err } + } + return nil +} + +func (s *ClientSynchronizer) processTrustedBatch(trustedBatch *types.Batch, dbTx pgx.Tx) error { + log.Debugf("processing trusted batch: %v", trustedBatch.Number) + txs := []ethTypes.Transaction{} + for _, transaction := range trustedBatch.Transactions { + tx := transaction.Tx.CoreTx() txs = append(txs, *tx) } trustedBatchL2Data, err := state.EncodeTransactions(txs) @@ -787,88 +1148,119 @@ func (s *ClientSynchronizer) processTrustedBatch(trustedBatch *pb.GetBatchRespon return err } - batch, err := s.state.GetBatchByNumber(s.ctx, trustedBatch.BatchNumber, nil) + batch, err := s.state.GetBatchByNumber(s.ctx, uint64(trustedBatch.Number), nil) if err != nil && err != state.ErrStateNotSynchronized { - log.Warnf("failed to get batch %v from local trusted state. Error: %v", trustedBatch.BatchNumber, err) + log.Warnf("failed to get batch %v from local trusted state. Error: %v", trustedBatch.Number, err) return err } // check if batch needs to be synchronized if batch != nil { - matchNumber := batch.BatchNumber == trustedBatch.BatchNumber - matchGER := batch.GlobalExitRoot.String() == trustedBatch.GlobalExitRoot - matchLER := batch.LocalExitRoot.String() == trustedBatch.LocalExitRoot - matchSR := batch.StateRoot.String() == trustedBatch.StateRoot - matchCoinbase := batch.Coinbase.String() == trustedBatch.Sequencer - matchTimestamp := uint64(batch.Timestamp.Unix()) == trustedBatch.Timestamp + matchNumber := batch.BatchNumber == uint64(trustedBatch.Number) + matchGER := batch.GlobalExitRoot.String() == trustedBatch.GlobalExitRoot.String() + matchLER := batch.LocalExitRoot.String() == trustedBatch.LocalExitRoot.String() + matchSR := batch.StateRoot.String() == trustedBatch.StateRoot.String() + matchCoinbase := batch.Coinbase.String() == trustedBatch.Coinbase.String() + matchTimestamp := uint64(batch.Timestamp.Unix()) == uint64(trustedBatch.Timestamp) matchL2Data := hex.EncodeToString(batch.BatchL2Data) == hex.EncodeToString(trustedBatchL2Data) if matchNumber && matchGER && matchLER && matchSR && matchCoinbase && matchTimestamp && matchL2Data { - log.Debugf("batch %v already synchronized", trustedBatch.BatchNumber) + log.Debugf("batch %v already synchronized", trustedBatch.Number) return nil } - log.Infof("batch %v needs to be updated", trustedBatch.BatchNumber) + log.Infof("batch %v needs to be updated", trustedBatch.Number) } else { - log.Infof("batch %v needs to be synchronized", trustedBatch.BatchNumber) + log.Infof("batch %v needs to be synchronized", trustedBatch.Number) } - log.Debugf("resetting trusted state from batch %v", trustedBatch.BatchNumber) - previousBatchNumber := trustedBatch.BatchNumber - 1 - if err := s.state.ResetTrustedState(s.ctx, previousBatchNumber, dbTx); err != nil { - log.Errorf("failed to reset trusted state", trustedBatch.BatchNumber) + log.Debugf("resetting trusted state from batch %v", trustedBatch.Number) + previousBatchNumber := trustedBatch.Number - 1 + if err := s.state.ResetTrustedState(s.ctx, uint64(previousBatchNumber), dbTx); err != nil { + log.Errorf("failed to reset trusted state", trustedBatch.Number) return err } - log.Debugf("opening batch %v", trustedBatch.BatchNumber) + log.Debugf("opening batch %v", trustedBatch.Number) processCtx := state.ProcessingContext{ - BatchNumber: trustedBatch.BatchNumber, - Coinbase: common.HexToAddress(trustedBatch.Sequencer), + BatchNumber: uint64(trustedBatch.Number), + Coinbase: common.HexToAddress(trustedBatch.Coinbase.String()), Timestamp: time.Unix(int64(trustedBatch.Timestamp), 0), - GlobalExitRoot: common.HexToHash(trustedBatch.GlobalExitRoot), + GlobalExitRoot: trustedBatch.GlobalExitRoot, } if err := s.state.OpenBatch(s.ctx, processCtx, dbTx); err != nil { - log.Errorf("error opening batch %d", trustedBatch.BatchNumber) + log.Errorf("error opening batch %d", trustedBatch.Number) return err } - log.Debugf("processing sequencer for batch %v", trustedBatch.BatchNumber) + log.Debugf("processing sequencer for batch %v", trustedBatch.Number) - processBatchResp, err := s.state.ProcessSequencerBatch(s.ctx, trustedBatch.BatchNumber, txs, dbTx) + processBatchResp, err := s.state.ProcessSequencerBatch(s.ctx, uint64(trustedBatch.Number), trustedBatchL2Data, metrics.SynchronizerCallerLabel, dbTx) if err != nil { - log.Errorf("error processing sequencer batch for batch: %d", trustedBatch.BatchNumber) + log.Errorf("error processing sequencer batch for batch: %d", trustedBatch.Number) return err } - log.Debugf("storing transactions for batch %v", trustedBatch.BatchNumber) - if err = s.state.StoreTransactions(s.ctx, trustedBatch.BatchNumber, processBatchResp.Responses, dbTx); err != nil { - log.Errorf("failed to store transactions for batch: %d", trustedBatch.BatchNumber) + log.Debugf("storing transactions for batch %v", trustedBatch.Number) + if err = s.state.StoreTransactions(s.ctx, uint64(trustedBatch.Number), processBatchResp.Responses, dbTx); err != nil { + log.Errorf("failed to store transactions for batch: %d", trustedBatch.Number) return err } log.Debug("trustedBatch.StateRoot ", trustedBatch.StateRoot) - isBatchClosed := trustedBatch.StateRoot != state.ZeroHash.String() + isBatchClosed := trustedBatch.StateRoot.String() != state.ZeroHash.String() if isBatchClosed { receipt := state.ProcessingReceipt{ - BatchNumber: trustedBatch.BatchNumber, + BatchNumber: uint64(trustedBatch.Number), StateRoot: processBatchResp.NewStateRoot, LocalExitRoot: processBatchResp.NewLocalExitRoot, + BatchL2Data: trustedBatchL2Data, + AccInputHash: trustedBatch.AccInputHash, } - log.Debugf("closing batch %v", trustedBatch.BatchNumber) + log.Debugf("closing batch %v", trustedBatch.Number) if err := s.state.CloseBatch(s.ctx, receipt, dbTx); err != nil { - log.Errorf("error closing batch %d", trustedBatch.BatchNumber) + log.Errorf("error closing batch %d", trustedBatch.Number) return err } } - if trustedBatch.ForcedBatchNumber > 0 { - log.Debugf("adding batch num %v for forced batch %v", trustedBatch.BatchNumber, trustedBatch.ForcedBatchNumber) - if err := s.state.AddBatchNumberInForcedBatch(s.ctx, trustedBatch.ForcedBatchNumber, trustedBatch.BatchNumber, dbTx); err != nil { - log.Errorf("error adding batch %v for forced batch %v", trustedBatch.BatchNumber, trustedBatch.ForcedBatchNumber) + log.Infof("batch %v synchronized", trustedBatch.Number) + return nil +} + +func (s *ClientSynchronizer) reorgPool(dbTx pgx.Tx) error { + latestBatchNum, err := s.etherMan.GetLatestBatchNumber() + if err != nil { + log.Error("error getting the latestBatchNumber virtualized in the smc. Error: ", err) + return err + } + batchNumber := latestBatchNum + 1 + // Get transactions that have to be included in the pool again + txs, err := s.state.GetReorgedTransactions(s.ctx, batchNumber, dbTx) + if err != nil { + log.Errorf("error getting txs from trusted state. BatchNumber: %d, error: %v", batchNumber, err) + return err + } + log.Debug("Reorged transactions: ", txs) + + // Remove txs from the pool + err = s.pool.DeleteReorgedTransactions(s.ctx, txs) + if err != nil { + log.Errorf("error deleting txs from the pool. BatchNumber: %d, error: %v", batchNumber, err) + return err + } + log.Debug("Delete reorged transactions") + + // Add txs to the pool + for _, tx := range txs { + // Insert tx in WIP status to avoid the sequencer to grab them before it gets restarted + // When the sequencer restarts, it will update the status to pending non-wip + err = s.pool.StoreTx(s.ctx, *tx, "", true) + if err != nil { + log.Errorf("error storing tx into the pool again. TxHash: %s. BatchNumber: %d, error: %v", tx.Hash().String(), batchNumber, err) return err } + log.Debug("Reorged transactions inserted in the pool: ", tx.Hash()) } - - log.Infof("batch %v synchronized", trustedBatch.BatchNumber) return nil } diff --git a/synchronizer/synchronizer_test.go b/synchronizer/synchronizer_test.go index 1ebf8e0c25..94d7218e3e 100644 --- a/synchronizer/synchronizer_test.go +++ b/synchronizer/synchronizer_test.go @@ -8,251 +8,804 @@ import ( cfgTypes "github.com/0xPolygonHermez/zkevm-node/config/types" "github.com/0xPolygonHermez/zkevm-node/etherman" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/jackc/pgx/v4" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) type mocks struct { - Etherman *ethermanMock - State *stateMock - DbTx *dbTxMock + Etherman *ethermanMock + State *stateMock + Pool *poolMock + EthTxManager *ethTxManagerMock + DbTx *dbTxMock + ZKEVMClient *zkEVMClientMock } -func TestTrustedStateReorg(t *testing.T) { - type testCase struct { - Name string - getTrustedBatch func(*mocks, context.Context, etherman.SequencedBatch) *state.Batch +// Test commented until we remove the fatal in checkTrustedReorg function +// func TestTrustedStateReorg(t *testing.T) { +// type testCase struct { +// Name string +// getTrustedBatch func(*mocks, context.Context, etherman.SequencedBatch) *state.Batch +// getTrustedReorg func(m *mocks, batchNumber, timestamp uint64) state.TrustedReorg +// } + +// setupMocks := func(m *mocks, tc *testCase) Synchronizer { +// genesis := state.Genesis{} +// cfg := Config{ +// SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, +// SyncChunkSize: 10, +// GenBlockNumber: uint64(123456), +// } + +// sync, err := NewSynchronizer(false, m.Etherman, m.State, m.Pool, m.EthTxManager, m.ZKEVMClient, genesis, cfg) +// require.NoError(t, err) + +// // state preparation +// ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }) +// m.State. +// On("BeginStateTransaction", ctxMatchBy). +// Run(func(args mock.Arguments) { +// ctx := args[0].(context.Context) +// parentHash := common.HexToHash("0x111") +// ethHeader := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} +// ethBlock := ethTypes.NewBlockWithHeader(ethHeader) +// lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64()} + +// m.State. +// On("GetLastBlock", ctx, m.DbTx). +// Return(lastBlock, nil). +// Once() + +// m.DbTx. +// On("Commit", ctx). +// Return(nil). +// Once() + +// m.Etherman. +// On("EthBlockByNumber", ctx, lastBlock.BlockNumber). +// Return(ethBlock, nil). +// Once() + +// var n *big.Int +// m.Etherman. +// On("HeaderByNumber", ctx, n). +// Return(ethHeader, nil). +// Once() + +// t := time.Now() +// sequencedBatch := etherman.SequencedBatch{ +// BatchNumber: uint64(1), +// Coinbase: common.HexToAddress("0x222"), +// TxHash: common.HexToHash("0x333"), +// PolygonZkEVMBatchData: polygonzkevm.PolygonZkEVMBatchData{ +// Transactions: []byte{}, +// GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, +// Timestamp: uint64(t.Unix()), +// MinForcedTimestamp: 0, +// }, +// } + +// ethermanBlock := etherman.Block{ +// BlockHash: ethBlock.Hash(), +// SequencedBatches: [][]etherman.SequencedBatch{{sequencedBatch}}, +// } +// blocks := []etherman.Block{ethermanBlock} +// order := map[common.Hash][]etherman.Order{ +// ethBlock.Hash(): { +// { +// Name: etherman.SequenceBatchesOrder, +// Pos: 0, +// }, +// }, +// } + +// fromBlock := ethBlock.NumberU64() + 1 +// toBlock := fromBlock + cfg.SyncChunkSize + +// m.Etherman. +// On("GetRollupInfoByBlockRange", ctx, fromBlock, &toBlock). +// Return(blocks, order, nil). +// Once() + +// m.ZKEVMClient. +// On("BatchNumber", ctx). +// Return(uint64(1), nil). +// Once() + +// m.State. +// On("BeginStateTransaction", ctx). +// Return(m.DbTx, nil). +// Once() + +// stateBlock := &state.Block{ +// BlockNumber: ethermanBlock.BlockNumber, +// BlockHash: ethermanBlock.BlockHash, +// ParentHash: ethermanBlock.ParentHash, +// ReceivedAt: ethermanBlock.ReceivedAt, +// } + +// m.State. +// On("AddBlock", ctx, stateBlock, m.DbTx). +// Return(nil). +// Once() + +// trustedBatch := tc.getTrustedBatch(m, ctx, sequencedBatch) + +// m.State. +// On("GetBatchByNumber", ctx, sequencedBatch.BatchNumber, m.DbTx). +// Return(trustedBatch, nil). +// Once() + +// sbatch := state.Batch{ +// BatchNumber: sequencedBatch.BatchNumber, +// Coinbase: common.HexToAddress("0x222"), +// BatchL2Data: []byte{}, +// Timestamp: time.Unix(int64(t.Unix()), 0), +// Transactions: nil, +// GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, +// ForcedBatchNum: nil, +// } +// m.State. +// On("ExecuteBatch", ctx, sbatch, false, m.DbTx). +// Return(&pb.ProcessBatchResponse{NewStateRoot: trustedBatch.StateRoot.Bytes()}, nil). +// Once() + +// seq := state.Sequence{ +// FromBatchNumber: 1, +// ToBatchNumber: 1, +// } +// m.State. +// On("AddSequence", ctx, seq, m.DbTx). +// Return(nil). +// Once() + +// m.State. +// On("AddAccumulatedInputHash", ctx, sequencedBatch.BatchNumber, common.Hash{}, m.DbTx). +// Return(nil). +// Once() + +// tr := tc.getTrustedReorg(m, sbatch.BatchNumber, uint64(t.Unix())) +// m.State. +// On("AddTrustedReorg", ctx, &tr, m.DbTx). +// Return(nil). +// Once() + +// m.Etherman. +// On("GetLatestBatchNumber"). +// Return(tr.BatchNumber-1, nil). +// Once() + +// txs := []*ethTypes.Transaction{ethTypes.NewTransaction(1, common.Address{}, big.NewInt(1), 1, big.NewInt(1), []byte{})} +// m.State. +// On("GetReorgedTransactions", ctx, tr.BatchNumber, m.DbTx). +// Return(txs, nil). +// Once() + +// m.Pool. +// On("DeleteReorgedTransactions", ctx, txs). +// Return(nil). +// Once() + +// m.Pool. +// On("StoreTx", ctx, *txs[0], "", true). +// Return(nil). +// Once() + +// m.State. +// On("ResetTrustedState", ctx, sequencedBatch.BatchNumber-1, m.DbTx). +// Return(nil). +// Once() + +// processingContext := state.ProcessingContext{ +// BatchNumber: sequencedBatch.BatchNumber, +// Coinbase: sequencedBatch.Coinbase, +// Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), +// GlobalExitRoot: sequencedBatch.GlobalExitRoot, +// } + +// m.State. +// On("ProcessAndStoreClosedBatch", ctx, processingContext, sequencedBatch.Transactions, m.DbTx, metrics.SynchronizerCallerLabel). +// Return(trustedBatch.StateRoot, nil). +// Once() + +// virtualBatch := &state.VirtualBatch{ +// BatchNumber: sequencedBatch.BatchNumber, +// TxHash: sequencedBatch.TxHash, +// Coinbase: sequencedBatch.Coinbase, +// BlockNumber: ethermanBlock.BlockNumber, +// } + +// m.State. +// On("AddVirtualBatch", ctx, virtualBatch, m.DbTx). +// Return(nil). +// Once() + +// m.DbTx. +// On("Commit", ctx). +// Run(func(args mock.Arguments) { sync.Stop() }). +// Return(nil). +// Once() + +// m.Etherman. +// On("GetLatestBatchNumber"). +// Return(uint64(10), nil). +// Once() + +// var nilDbTx pgx.Tx +// m.State. +// On("GetLastBatchNumber", ctx, nilDbTx). +// Return(uint64(10), nil). +// Once() +// }). +// Return(m.DbTx, nil). +// Once() + +// return sync +// } + +// testCases := []testCase{ +// { +// Name: "Transactions are different", +// getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { +// return &state.Batch{ +// BatchNumber: 1, +// BatchL2Data: []byte{1}, +// GlobalExitRoot: sequencedBatch.GlobalExitRoot, +// Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), +// Coinbase: sequencedBatch.Coinbase, +// } +// }, +// getTrustedReorg: func(m *mocks, batchNumber, timestamp uint64) state.TrustedReorg { +// return state.TrustedReorg{ +// BatchNumber: batchNumber, +// Reason: "Different field BatchL2Data. Virtual: , Trusted: 01\n", +// } +// }, +// }, +// { +// Name: "Global Exit Root is different", +// getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { +// return &state.Batch{ +// BatchNumber: 1, +// BatchL2Data: sequencedBatch.Transactions, +// GlobalExitRoot: common.HexToHash("0x999888777"), +// Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), +// Coinbase: sequencedBatch.Coinbase, +// } +// }, +// getTrustedReorg: func(m *mocks, batchNumber, timestamp uint64) state.TrustedReorg { +// return state.TrustedReorg{ +// BatchNumber: batchNumber, +// Reason: "Different field GlobalExitRoot. Virtual: 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20, Trusted: 0x0000000000000000000000000000000000000000000000000000000999888777\n", +// } +// }, +// }, +// { +// Name: "Timestamp is different", +// getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { +// return &state.Batch{ +// BatchNumber: 1, +// BatchL2Data: sequencedBatch.Transactions, +// GlobalExitRoot: sequencedBatch.GlobalExitRoot, +// Timestamp: time.Unix(int64(0), 0), +// Coinbase: sequencedBatch.Coinbase, +// } +// }, +// getTrustedReorg: func(m *mocks, batchNumber, timestamp uint64) state.TrustedReorg { +// return state.TrustedReorg{ +// BatchNumber: batchNumber, +// Reason: "Different field Timestamp. Virtual: " + strconv.FormatUint(timestamp, 10) + ", Trusted: 0\n", +// } +// }, +// }, +// { +// Name: "Coinbase is different", +// getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { +// return &state.Batch{ +// BatchNumber: 1, +// BatchL2Data: sequencedBatch.Transactions, +// GlobalExitRoot: sequencedBatch.GlobalExitRoot, +// Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), +// Coinbase: common.HexToAddress("0x999888777"), +// } +// }, +// getTrustedReorg: func(m *mocks, batchNumber, timestamp uint64) state.TrustedReorg { +// return state.TrustedReorg{ +// BatchNumber: batchNumber, +// Reason: "Different field Coinbase. Virtual: 0x0000000000000000000000000000000000000222, Trusted: 0x0000000000000000000000000000000999888777\n", +// } +// }, +// }, +// } + +// m := mocks{ +// Etherman: newEthermanMock(t), +// State: newStateMock(t), +// Pool: newPoolMock(t), +// EthTxManager: newEthTxManagerMock(t), +// DbTx: newDbTxMock(t), +// ZKEVMClient: newZkEVMClientMock(t), +// } + +// // start synchronizing +// for _, tc := range testCases { +// t.Run(tc.Name, func(t *testing.T) { +// testCase := tc +// sync := setupMocks(&m, &testCase) +// err := sync.Sync() +// require.NoError(t, err) +// }) +// } +// } + +func TestForcedBatch(t *testing.T) { + genesis := state.Genesis{ + GenesisBlockNum: uint64(123456), + } + cfg := Config{ + SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, + SyncChunkSize: 10, } - setupMocks := func(m *mocks, tc *testCase) Synchronizer { - genBlockNumber := uint64(123456) - genesis := state.Genesis{} - cfg := Config{ - SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, - SyncChunkSize: 10, - } - reorgTrustedStateChan := make(chan struct{}) - sync, err := NewSynchronizer(true, m.Etherman, m.State, genBlockNumber, genesis, cfg) - require.NoError(t, err) - - go func() { - for { - select { - case <-reorgTrustedStateChan: - t.Log("Trusted reorg receive in the channel") - return - case <-context.Background().Done(): - return - } - } - }() - // state preparation - ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }) - m.State. - On("BeginStateTransaction", ctxMatchBy). - Run(func(args mock.Arguments) { - ctx := args[0].(context.Context) - parentHash := common.HexToHash("0x111") - ethHeader := &types.Header{Number: big.NewInt(1), ParentHash: parentHash} - ethBlock := types.NewBlockWithHeader(ethHeader) - lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64()} - - m.State. - On("GetLastBlock", ctx, m.DbTx). - Return(lastBlock, nil). - Once() + m := mocks{ + Etherman: newEthermanMock(t), + State: newStateMock(t), + Pool: newPoolMock(t), + DbTx: newDbTxMock(t), + ZKEVMClient: newZkEVMClientMock(t), + } - m.DbTx. - On("Commit", ctx). - Return(nil). - Once() + sync, err := NewSynchronizer(false, m.Etherman, m.State, m.Pool, m.EthTxManager, m.ZKEVMClient, genesis, cfg) + require.NoError(t, err) - m.Etherman. - On("EthBlockByNumber", ctx, lastBlock.BlockNumber). - Return(ethBlock, nil). - Once() + // state preparation + ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }) + m.State. + On("BeginStateTransaction", ctxMatchBy). + Run(func(args mock.Arguments) { + ctx := args[0].(context.Context) + parentHash := common.HexToHash("0x111") + ethHeader := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} + ethBlock := ethTypes.NewBlockWithHeader(ethHeader) + lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64()} - var n *big.Int - m.Etherman. - On("HeaderByNumber", ctx, n). - Return(ethHeader, nil). - Once() + m.State. + On("GetLastBlock", ctx, m.DbTx). + Return(lastBlock, nil). + Once() + + m.State. + On("GetLastBatchNumber", ctx, m.DbTx). + Return(uint64(10), nil). + Once() + + m.State. + On("SetInitSyncBatch", ctx, uint64(10), m.DbTx). + Return(nil). + Once() + + m.DbTx. + On("Commit", ctx). + Return(nil). + Once() + + m.Etherman. + On("GetLatestBatchNumber"). + Return(uint64(10), nil). + Once() + + var nilDbTx pgx.Tx + m.State. + On("GetLastBatchNumber", ctx, nilDbTx). + Return(uint64(10), nil). + Once() + + m.Etherman. + On("GetLatestVerifiedBatchNum"). + Return(uint64(10), nil). + Once() + + m.State. + On("SetLastBatchInfoSeenOnEthereum", ctx, uint64(10), uint64(10), nilDbTx). + Return(nil). + Once() - sequencedBatch := etherman.SequencedBatch{ - BatchNumber: uint64(1), - Coinbase: common.HexToAddress("0x222"), - TxHash: common.HexToHash("0x333"), - ProofOfEfficiencyBatchData: proofofefficiency.ProofOfEfficiencyBatchData{ - Transactions: []byte{}, - GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, - Timestamp: uint64(time.Now().Unix()), - ForceBatchesTimestamp: []uint64{}, + m.Etherman. + On("EthBlockByNumber", ctx, lastBlock.BlockNumber). + Return(ethBlock, nil). + Once() + + var n *big.Int + m.Etherman. + On("HeaderByNumber", ctx, n). + Return(ethHeader, nil). + Once() + + t := time.Now() + sequencedBatch := etherman.SequencedBatch{ + BatchNumber: uint64(2), + Coinbase: common.HexToAddress("0x222"), + SequencerAddr: common.HexToAddress("0x00"), + TxHash: common.HexToHash("0x333"), + PolygonZkEVMBatchData: polygonzkevm.PolygonZkEVMBatchData{ + Transactions: []byte{}, + GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, + Timestamp: uint64(t.Unix()), + MinForcedTimestamp: 1000, //ForcedBatch + }, + } + + forceb := []etherman.ForcedBatch{{ + BlockNumber: lastBlock.BlockNumber, + ForcedBatchNumber: 1, + Sequencer: sequencedBatch.Coinbase, + GlobalExitRoot: sequencedBatch.GlobalExitRoot, + RawTxsData: sequencedBatch.Transactions, + ForcedAt: time.Unix(int64(sequencedBatch.MinForcedTimestamp), 0), + }} + + ethermanBlock := etherman.Block{ + BlockHash: ethBlock.Hash(), + SequencedBatches: [][]etherman.SequencedBatch{{sequencedBatch}}, + ForcedBatches: forceb, + } + blocks := []etherman.Block{ethermanBlock} + order := map[common.Hash][]etherman.Order{ + ethBlock.Hash(): { + { + Name: etherman.ForcedBatchesOrder, + Pos: 0, }, - } - - ethermanBlock := etherman.Block{ - BlockHash: ethBlock.Hash(), - SequencedBatches: [][]etherman.SequencedBatch{{sequencedBatch}}, - } - blocks := []etherman.Block{ethermanBlock} - order := map[common.Hash][]etherman.Order{ - ethBlock.Hash(): { - { - Name: etherman.SequenceBatchesOrder, - Pos: 0, - }, + { + Name: etherman.SequenceBatchesOrder, + Pos: 0, }, - } + }, + } - fromBlock := ethBlock.NumberU64() + 1 - toBlock := fromBlock + cfg.SyncChunkSize + fromBlock := ethBlock.NumberU64() + 1 + toBlock := fromBlock + cfg.SyncChunkSize - m.Etherman. - On("GetRollupInfoByBlockRange", ctx, fromBlock, &toBlock). - Return(blocks, order, nil). - Once() + m.Etherman. + On("GetRollupInfoByBlockRange", ctx, fromBlock, &toBlock). + Return(blocks, order, nil). + Once() - m.State. - On("BeginStateTransaction", ctx). - Return(m.DbTx, nil). - Once() + m.ZKEVMClient. + On("BatchNumber", ctx). + Return(uint64(1), nil). + Once() - stateBlock := &state.Block{ - BlockNumber: ethermanBlock.BlockNumber, - BlockHash: ethermanBlock.BlockHash, - ParentHash: ethermanBlock.ParentHash, - ReceivedAt: ethermanBlock.ReceivedAt, - } + m.State. + On("BeginStateTransaction", ctx). + Return(m.DbTx, nil). + Once() - m.State. - On("AddBlock", ctx, stateBlock, m.DbTx). - Return(nil). - Once() + stateBlock := &state.Block{ + BlockNumber: ethermanBlock.BlockNumber, + BlockHash: ethermanBlock.BlockHash, + ParentHash: ethermanBlock.ParentHash, + ReceivedAt: ethermanBlock.ReceivedAt, + } - trustedBatch := tc.getTrustedBatch(m, ctx, sequencedBatch) + m.State. + On("AddBlock", ctx, stateBlock, m.DbTx). + Return(nil). + Once() - m.State. - On("GetBatchByNumber", ctx, sequencedBatch.BatchNumber, m.DbTx). - Return(trustedBatch, nil). - Once() + fb := []state.ForcedBatch{{ + BlockNumber: lastBlock.BlockNumber, + ForcedBatchNumber: 1, + Sequencer: sequencedBatch.Coinbase, + GlobalExitRoot: sequencedBatch.GlobalExitRoot, + RawTxsData: sequencedBatch.Transactions, + ForcedAt: time.Unix(int64(sequencedBatch.MinForcedTimestamp), 0), + }} - m.State. - On("ResetTrustedState", ctx, sequencedBatch.BatchNumber-1, m.DbTx). - Return(nil). - Once() + m.State. + On("AddForcedBatch", ctx, &fb[0], m.DbTx). + Return(nil). + Once() - processingContext := state.ProcessingContext{ - BatchNumber: sequencedBatch.BatchNumber, - Coinbase: sequencedBatch.Coinbase, - Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), - GlobalExitRoot: sequencedBatch.GlobalExitRoot, - } + m.State. + On("GetNextForcedBatches", ctx, 1, m.DbTx). + Return(fb, nil). + Once() - m.State. - On("ProcessAndStoreClosedBatch", ctx, processingContext, sequencedBatch.Transactions, m.DbTx). - Return(nil). - Once() + trustedBatch := &state.Batch{ + BatchL2Data: sequencedBatch.Transactions, + GlobalExitRoot: sequencedBatch.GlobalExitRoot, + Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), + Coinbase: sequencedBatch.Coinbase, + } - virtualBatch := &state.VirtualBatch{ - BatchNumber: sequencedBatch.BatchNumber, - TxHash: sequencedBatch.TxHash, - Coinbase: sequencedBatch.Coinbase, - BlockNumber: ethermanBlock.BlockNumber, - } + m.State. + On("GetBatchByNumber", ctx, sequencedBatch.BatchNumber, m.DbTx). + Return(trustedBatch, nil). + Once() - m.State. - On("AddVirtualBatch", ctx, virtualBatch, m.DbTx). - Return(nil). + var forced uint64 = 1 + sbatch := state.Batch{ + BatchNumber: sequencedBatch.BatchNumber, + Coinbase: common.HexToAddress("0x222"), + BatchL2Data: []byte{}, + Timestamp: time.Unix(int64(t.Unix()), 0), + Transactions: nil, + GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, + ForcedBatchNum: &forced, + } + m.State. //ExecuteBatch(s.ctx, batch.BatchNumber, batch.BatchL2Data, dbTx + On("ExecuteBatch", ctx, sbatch, false, m.DbTx). + Return(&pb.ProcessBatchResponse{NewStateRoot: trustedBatch.StateRoot.Bytes()}, nil). Once() - m.DbTx. - On("Commit", ctx). - Run(func(args mock.Arguments) { sync.Stop() }). - Return(nil). - Once() + virtualBatch := &state.VirtualBatch{ + BatchNumber: sequencedBatch.BatchNumber, + TxHash: sequencedBatch.TxHash, + Coinbase: sequencedBatch.Coinbase, + BlockNumber: ethermanBlock.BlockNumber, + } - m.Etherman. - On("GetLatestBatchNumber"). - Return(uint64(10), nil). - Once() + m.State. + On("AddVirtualBatch", ctx, virtualBatch, m.DbTx). + Return(nil). + Once() - var nilDbTx pgx.Tx - m.State. - On("GetLastBatchNumber", ctx, nilDbTx). - Return(uint64(10), nil). - Once() - }). - Return(m.DbTx, nil). - Once() + seq := state.Sequence{ + FromBatchNumber: 2, + ToBatchNumber: 2, + } + m.State. + On("AddSequence", ctx, seq, m.DbTx). + Return(nil). + Once() - return sync - } + m.State. + On("AddAccumulatedInputHash", ctx, sequencedBatch.BatchNumber, common.Hash{}, m.DbTx). + Return(nil). + Once() - testCases := []testCase{ - { - Name: "Transactions are different", - getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { - return &state.Batch{ - BatchL2Data: []byte{1}, - GlobalExitRoot: sequencedBatch.GlobalExitRoot, - Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), - Coinbase: sequencedBatch.Coinbase, - } - }, - }, - { - Name: "Global Exit Root is different", - getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { - return &state.Batch{ - BatchL2Data: sequencedBatch.Transactions, - GlobalExitRoot: common.HexToHash("0x999888777"), - Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), - Coinbase: sequencedBatch.Coinbase, - } - }, - }, - { - Name: "Timestamp is different", - getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { - return &state.Batch{ - BatchL2Data: sequencedBatch.Transactions, - GlobalExitRoot: sequencedBatch.GlobalExitRoot, - Timestamp: time.Unix(int64(0), 0), - Coinbase: sequencedBatch.Coinbase, - } - }, - }, - { - Name: "Coinbase is different", - getTrustedBatch: func(m *mocks, ctx context.Context, sequencedBatch etherman.SequencedBatch) *state.Batch { - return &state.Batch{ - BatchL2Data: sequencedBatch.Transactions, - GlobalExitRoot: sequencedBatch.GlobalExitRoot, - Timestamp: time.Unix(int64(sequencedBatch.Timestamp), 0), - Coinbase: common.HexToAddress("0x999888777"), - } - }, - }, + m.DbTx. + On("Commit", ctx). + Run(func(args mock.Arguments) { sync.Stop() }). + Return(nil). + Once() + }). + Return(m.DbTx, nil). + Once() + + err = sync.Sync() + require.NoError(t, err) +} + +func TestSequenceForcedBatch(t *testing.T) { + genesis := state.Genesis{ + GenesisBlockNum: uint64(123456), + } + cfg := Config{ + SyncInterval: cfgTypes.Duration{Duration: 1 * time.Second}, + SyncChunkSize: 10, } m := mocks{ - Etherman: newEthermanMock(t), - State: newStateMock(t), - DbTx: newDbTxMock(t), + Etherman: newEthermanMock(t), + State: newStateMock(t), + Pool: newPoolMock(t), + DbTx: newDbTxMock(t), + ZKEVMClient: newZkEVMClientMock(t), } - // start synchronizing - for _, tc := range testCases { - t.Run(tc.Name, func(t *testing.T) { - testCase := tc - sync := setupMocks(&m, &testCase) - err := sync.Sync() - require.NoError(t, err) - }) - } + sync, err := NewSynchronizer(true, m.Etherman, m.State, m.Pool, m.EthTxManager, m.ZKEVMClient, genesis, cfg) + require.NoError(t, err) + + // state preparation + ctxMatchBy := mock.MatchedBy(func(ctx context.Context) bool { return ctx != nil }) + m.State. + On("BeginStateTransaction", ctxMatchBy). + Run(func(args mock.Arguments) { + ctx := args[0].(context.Context) + parentHash := common.HexToHash("0x111") + ethHeader := ðTypes.Header{Number: big.NewInt(1), ParentHash: parentHash} + ethBlock := ethTypes.NewBlockWithHeader(ethHeader) + lastBlock := &state.Block{BlockHash: ethBlock.Hash(), BlockNumber: ethBlock.Number().Uint64()} + + m.State. + On("GetLastBlock", ctx, m.DbTx). + Return(lastBlock, nil). + Once() + + m.State. + On("GetLastBatchNumber", ctx, m.DbTx). + Return(uint64(10), nil). + Once() + + m.State. + On("SetInitSyncBatch", ctx, uint64(10), m.DbTx). + Return(nil). + Once() + + m.DbTx. + On("Commit", ctx). + Return(nil). + Once() + + m.Etherman. + On("GetLatestBatchNumber"). + Return(uint64(10), nil). + Once() + + var nilDbTx pgx.Tx + m.State. + On("GetLastBatchNumber", ctx, nilDbTx). + Return(uint64(10), nil). + Once() + + m.Etherman. + On("GetLatestVerifiedBatchNum"). + Return(uint64(10), nil). + Once() + + m.State. + On("SetLastBatchInfoSeenOnEthereum", ctx, uint64(10), uint64(10), nilDbTx). + Return(nil). + Once() + + m.Etherman. + On("EthBlockByNumber", ctx, lastBlock.BlockNumber). + Return(ethBlock, nil). + Once() + + var n *big.Int + m.Etherman. + On("HeaderByNumber", ctx, n). + Return(ethHeader, nil). + Once() + + sequencedForceBatch := etherman.SequencedForceBatch{ + BatchNumber: uint64(2), + Coinbase: common.HexToAddress("0x222"), + TxHash: common.HexToHash("0x333"), + PolygonZkEVMForcedBatchData: polygonzkevm.PolygonZkEVMForcedBatchData{ + Transactions: []byte{}, + GlobalExitRoot: [32]byte{1, 2, 3, 4, 5, 6, 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}, + MinForcedTimestamp: 1000, //ForcedBatch + }, + } + + forceb := []etherman.ForcedBatch{{ + BlockNumber: lastBlock.BlockNumber, + ForcedBatchNumber: 1, + Sequencer: sequencedForceBatch.Coinbase, + GlobalExitRoot: sequencedForceBatch.GlobalExitRoot, + RawTxsData: sequencedForceBatch.Transactions, + ForcedAt: time.Unix(int64(sequencedForceBatch.MinForcedTimestamp), 0), + }} + + ethermanBlock := etherman.Block{ + BlockHash: ethBlock.Hash(), + SequencedForceBatches: [][]etherman.SequencedForceBatch{{sequencedForceBatch}}, + ForcedBatches: forceb, + } + blocks := []etherman.Block{ethermanBlock} + order := map[common.Hash][]etherman.Order{ + ethBlock.Hash(): { + { + Name: etherman.ForcedBatchesOrder, + Pos: 0, + }, + { + Name: etherman.SequenceForceBatchesOrder, + Pos: 0, + }, + }, + } + + fromBlock := ethBlock.NumberU64() + 1 + toBlock := fromBlock + cfg.SyncChunkSize + + m.Etherman. + On("GetRollupInfoByBlockRange", ctx, fromBlock, &toBlock). + Return(blocks, order, nil). + Once() + + m.State. + On("BeginStateTransaction", ctx). + Return(m.DbTx, nil). + Once() + + stateBlock := &state.Block{ + BlockNumber: ethermanBlock.BlockNumber, + BlockHash: ethermanBlock.BlockHash, + ParentHash: ethermanBlock.ParentHash, + ReceivedAt: ethermanBlock.ReceivedAt, + } + + m.State. + On("AddBlock", ctx, stateBlock, m.DbTx). + Return(nil). + Once() + + fb := []state.ForcedBatch{{ + BlockNumber: lastBlock.BlockNumber, + ForcedBatchNumber: 1, + Sequencer: sequencedForceBatch.Coinbase, + GlobalExitRoot: sequencedForceBatch.GlobalExitRoot, + RawTxsData: sequencedForceBatch.Transactions, + ForcedAt: time.Unix(int64(sequencedForceBatch.MinForcedTimestamp), 0), + }} + + m.State. + On("AddForcedBatch", ctx, &fb[0], m.DbTx). + Return(nil). + Once() + + m.State. + On("GetLastVirtualBatchNum", ctx, m.DbTx). + Return(uint64(1), nil). + Once() + + m.State. + On("ResetTrustedState", ctx, uint64(1), m.DbTx). + Return(nil). + Once() + + m.State. + On("GetNextForcedBatches", ctx, 1, m.DbTx). + Return(fb, nil). + Once() + + f := uint64(1) + processingContext := state.ProcessingContext{ + BatchNumber: sequencedForceBatch.BatchNumber, + Coinbase: sequencedForceBatch.Coinbase, + Timestamp: ethBlock.ReceivedAt, + GlobalExitRoot: sequencedForceBatch.GlobalExitRoot, + ForcedBatchNum: &f, + } + + m.State. + On("ProcessAndStoreClosedBatch", ctx, processingContext, sequencedForceBatch.Transactions, m.DbTx, metrics.SynchronizerCallerLabel). + Return(common.Hash{}, nil). + Once() + + virtualBatch := &state.VirtualBatch{ + BatchNumber: sequencedForceBatch.BatchNumber, + TxHash: sequencedForceBatch.TxHash, + Coinbase: sequencedForceBatch.Coinbase, + SequencerAddr: sequencedForceBatch.Coinbase, + BlockNumber: ethermanBlock.BlockNumber, + } + + m.State. + On("AddVirtualBatch", ctx, virtualBatch, m.DbTx). + Return(nil). + Once() + + seq := state.Sequence{ + FromBatchNumber: 2, + ToBatchNumber: 2, + } + m.State. + On("AddSequence", ctx, seq, m.DbTx). + Return(nil). + Once() + + m.DbTx. + On("Commit", ctx). + Run(func(args mock.Arguments) { sync.Stop() }). + Return(nil). + Once() + }). + Return(m.DbTx, nil). + Once() + + err = sync.Sync() + require.NoError(t, err) } diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000000..4ba9b7a195 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,530 @@ +DOCKERCOMPOSE := docker-compose -f docker-compose.yml +DOCKERCOMPOSEAPPSEQ := zkevm-sequencer +DOCKERCOMPOSEAPPSEQSENDER := zkevm-sequence-sender +DOCKERCOMPOSEAPPL2GASP := zkevm-l2gaspricer +DOCKERCOMPOSEAPPAGG := zkevm-aggregator +DOCKERCOMPOSEAPPRPC := zkevm-json-rpc +DOCKERCOMPOSEAPPSYNC := zkevm-sync +DOCKERCOMPOSEAPPETHTXMANAGER := zkevm-eth-tx-manager +DOCKERCOMPOSESTATEDB := zkevm-state-db +DOCKERCOMPOSEPOOLDB := zkevm-pool-db +DOCKERCOMPOSEEVENTDB := zkevm-event-db +DOCKERCOMPOSENETWORK := zkevm-mock-l1-network +DOCKERCOMPOSEEXPLORERL1 := zkevm-explorer-l1 +DOCKERCOMPOSEEXPLORERL1DB := zkevm-explorer-l1-db +DOCKERCOMPOSEEXPLORERL2 := zkevm-explorer-l2 +DOCKERCOMPOSEEXPLORERL2DB := zkevm-explorer-l2-db +DOCKERCOMPOSEEXPLORERRPC := zkevm-explorer-json-rpc +DOCKERCOMPOSEZKPROVER := zkevm-prover +DOCKERCOMPOSEPERMISSIONLESSDB := zkevm-permissionless-db +DOCKERCOMPOSEPERMISSIONLESSNODE := zkevm-permissionless-node +DOCKERCOMPOSEPERMISSIONLESSZKPROVER := zkevm-permissionless-prover +DOCKERCOMPOSENODEAPPROVE := zkevm-approve +DOCKERCOMPOSEMETRICS := zkevm-metrics +DOCKERCOMPOSEGRAFANA := grafana + +RUNSTATEDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSESTATEDB) +RUNPOOLDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPOOLDB) +RUNEVENTDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEVENTDB) +RUNSEQUENCER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPSEQ) +RUNSEQUENCESENDER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPSEQSENDER) +RUNL2GASPRICER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPL2GASP) +RUNAGGREGATOR := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPAGG) +RUNJSONRPC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPRPC) +RUNSYNC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPSYNC) +RUNETHTXMANAGER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEAPPETHTXMANAGER) +RUNGRAFANA := DOCKERGID=`stat -c '%g' /var/run/docker.sock` $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEGRAFANA) + +RUNL1NETWORK := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSENETWORK) +RUNEXPLORERL1 := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL1) +RUNEXPLORERL1DB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL1DB) +RUNEXPLORERL2 := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL2) +RUNEXPLORERL2DB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERL2DB) +RUNEXPLORERJSONRPC := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEEXPLORERRPC) +RUNZKPROVER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEZKPROVER) + +RUNPERMISSIONLESSDB := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPERMISSIONLESSDB) +RUNPERMISSIONLESSNODE := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPERMISSIONLESSNODE) +RUNPERMISSIONLESSZKPROVER := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEPERMISSIONLESSZKPROVER) + +RUNAPPROVE := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSENODEAPPROVE) + +RUNMETRICS := $(DOCKERCOMPOSE) up -d $(DOCKERCOMPOSEMETRICS) + +RUN := $(DOCKERCOMPOSE) up -d + +STOPSTATEDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSESTATEDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSESTATEDB) +STOPPOOLDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPOOLDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPOOLDB) +STOPEVENTDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEVENTDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEVENTDB) +STOPSEQUENCER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPSEQ) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPSEQ) +STOPSEQUENCESENDER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPSEQSENDER) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPSEQSENDER) +STOPL2GASPRICER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPL2GASP) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPL2GASP) +STOPAGGREGATOR := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPAGG) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPAGG) +STOPJSONRPC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPRPC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPRPC) +STOPSYNC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPSYNC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPSYNC) +STOPETHTXMANAGER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEAPPETHTXMANAGER) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEAPPETHTXMANAGER) +STOPGRAFANA := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEGRAFANA) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEGRAFANA) + +STOPNETWORK := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSENETWORK) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSENETWORK) +STOPEXPLORERL1 := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL1) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL1) +STOPEXPLORERL1DB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL1DB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL1DB) +STOPEXPLORERL2 := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL2) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL2) +STOPEXPLORERL2DB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERL2DB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERL2DB) +STOPEXPLORERJSONRPC := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEEXPLORERRPC) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEEXPLORERRPC) +STOPZKPROVER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEZKPROVER) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEZKPROVER) + +STOPPERMISSIONLESSDB := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPERMISSIONLESSDB) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPERMISSIONLESSDB) +STOPPERMISSIONLESSNODE := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPERMISSIONLESSNODE) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPERMISSIONLESSNODE) +STOPPERMISSIONLESSZKPROVER := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEPERMISSIONLESSZKPROVER) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEPERMISSIONLESSZKPROVER) + +STOPAPPROVE := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSENODEAPPROVE) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSENODEAPPROVE) + +STOPMETRICS := $(DOCKERCOMPOSE) stop $(DOCKERCOMPOSEMETRICS) && $(DOCKERCOMPOSE) rm -f $(DOCKERCOMPOSEMETRICS) + +STOP := $(DOCKERCOMPOSE) down --remove-orphans + +.PHONY: test-full-non-e2e +test-full-non-e2e: stop ## Runs non-e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + $(RUNZKPROVER) + sleep 7 + $(RUNL1NETWORK) + sleep 15 + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -short -race -p 1 -timeout 60s ../... + +.PHONY: test-e2e-group-1 +test-e2e-group-1: stop ## Runs group 1 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group1/... + +.PHONY: test-e2e-group-2 +test-e2e-group-2: stop ## Runs group 2 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group2/... + +.PHONY: test-e2e-group-3 +test-e2e-group-3: stop ## Runs group 3 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group3/... + +.PHONY: test-e2e-group-4 +test-e2e-group-4: stop ## Runs group 4 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group4/... + +.PHONY: test-e2e-group-5 +test-e2e-group-5: stop ## Runs group 5 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 1200s ../ci/e2e-group5/... + +.PHONY: test-e2e-group-6 +test-e2e-group-6: stop ## Runs group 6 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group6/... + +.PHONY: test-e2e-group-7 +test-e2e-group-7: stop ## Runs group 7 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 600s ../ci/e2e-group7/... + +.PHONY: test-e2e-group-8 +test-e2e-group-8: stop ## Runs group 8 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 1200s ../ci/e2e-group8/... + + +.PHONY: test-e2e-group-9 +test-e2e-group-9: stop ## Runs group 9 e2e tests checking race conditions + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + trap '$(STOP)' EXIT; MallocNanoZone=0 go test -count=1 -race -v -p 1 -timeout 2000s ../ci/e2e-group9/... + +.PHONY: benchmark-sequencer-eth-transfers +benchmark-sequencer-eth-transfers: stop + $(RUNL1NETWORK) + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + $(RUNSYNC) + sleep 2 + $(RUNL2GASPRICER) + $(RUNJSONRPC) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + @ cd benchmarks/sequencer/eth-transfers ; \ + mkdir -p results ; \ + touch ./results/out.dat ; \ + go test -bench=. -timeout=600m | tee ./results/out.dat ; + +.PHONY: benchmark-sequencer-erc20-transfers +benchmark-sequencer-erc20-transfers: stop + $(RUNL1NETWORK) + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + sleep 5 + $(RUNZKPROVER) + $(RUNSYNC) + sleep 2 + $(RUNL2GASPRICER) + $(RUNJSONRPC) + docker ps -a + docker logs $(DOCKERCOMPOSEZKPROVER) + @ cd benchmarks/sequencer/erc20-transfers ; \ + mkdir -p results ; \ + touch ./results/out.dat ; \ + go test -bench=. -timeout=600m | tee ./results/out.dat ; + +.PHONY: run-db +run-db: ## Runs the node database + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + +.PHONY: stop-db +stop-db: ## Stops the node database + $(STOPEVENTDB) + $(STOPPOOLDB) + $(STOPSTATEDB) + +.PHONY: run-node +run-node: ## Runs the node + $(RUNETHTXMANAGER) + $(RUNSYNC) + sleep 2 + $(RUNSEQUENCER) + $(RUNSEQUENCESENDER) + $(RUNL2GASPRICER) + $(RUNAGGREGATOR) + $(RUNJSONRPC) + +.PHONY: stop-node +stop-node: ## Stops the node + $(STOPSEQUENCER) + $(STOPSEQUENCESENDER) + $(STOPJSONRPC) + $(STOPL2GASPRICER) + $(STOPAGGREGATOR) + $(STOPSYNC) + $(STOPETHTXMANAGER) + +.PHONY: run-network +run-network: ## Runs the l1 network + $(RUNL1NETWORK) + +.PHONY: stop-network +stop-network: ## Stops the l1 network + $(STOPNETWORK) + +.PHONY: run-zkprover +run-zkprover: ## Runs zkprover + $(RUNZKPROVER) + +.PHONY: stop-zkprover +stop-zkprover: ## Stops zkprover + $(STOPZKPROVER) + +.PHONY: run-l1-explorer +run-l1-explorer: ## Runs L1 blockscan explorer + $(RUNEXPLORERL1DB) + $(RUNEXPLORERL1) + +.PHONY: run-l2-explorer +run-l2-explorer: ## Runs L2 blockscan explorer + $(RUNEXPLORERL2DB) + $(RUNEXPLORERJSONRPC) + $(RUNEXPLORERL2) + +.PHONY: run-l2-explorer-json-rpc +run-l2-explorer-json-rpc: ## Runs L2 explorer json rpc + $(RUNEXPLORERJSONRPC) + +.PHONY: stop-l2-explorer-json-rpc +stop-l2-explorer-json-rpc: ## Stops L2 explorer json rpc + $(STOPEXPLORERJSONRPC) + +.PHONY: run-explorer +run-explorer: run-l1-explorer run-l2-explorer ## Runs both L1 and L2 explorers + +.PHONY: stop-explorer +stop-explorer: ## Stops the explorer + $(STOPEXPLORERL2) + $(STOPEXPLORERL1) + $(STOPEXPLORERJSONRPC) + $(STOPEXPLORERL2DB) + $(STOPEXPLORERL1DB) + +.PHONY: run-explorer-db +run-explorer-db: ## Runs the explorer database + $(RUNEXPLORERL1DB) + $(RUNEXPLORERL2DB) + +.PHONY: stop-explorer-db +stop-explorer-db: ## Stops the explorer database + $(STOPEXPLORERL2DB) + $(STOPEXPLORERL1DB) + +.PHONY: run-seq +run-seq: ## runs the sequencer + $(RUNSEQUENCER) + +.PHONY: stop-seq +stop-seq: ## stops the sequencer + $(STOPSEQUENCER) + +.PHONY: run-seqsender +run-seqsender: ## runs the sequencer sender + $(RUNSEQUENCESENDER) + +.PHONY: stop-seqsender +stop-seqsender: ## stops the sequencer sender + $(STOPSEQUENCESENDER) + +.PHONY: run-sync +run-sync: ## runs the synchronizer + $(RUNSYNC) + +.PHONY: stop-sync +stop-sync: ## stops the synchronizer + $(STOPSYNC) + +.PHONY: run-json-rpc +run-json-rpc: ## runs the JSON-RPC + $(RUNJSONRPC) + +.PHONY: stop-json-rpc +stop-json-rpc: ## stops the JSON-RPC + $(STOPJSONRPC) + +.PHONY: run-l2gaspricer +run-l2gaspricer: ## runs the L2 Gas Price component + $(RUNL2GASPRICER) + +.PHONY: stop-l2gaspricer +stop-l2gaspricer: ## stops the L2 Gas Price component + $(STOPL2GASPRICER) + +.PHONY: run-eth-tx-manager +run-eth-tx-manager: ## Runs the eth tx manager service + $(RUNETHTXMANAGER) + +.PHONY: stop-eth-tx-manager +stop-eth-tx-manager: ## Stops the eth tx manager service + $(STOPETHTXMANAGER) + +.PHONY: run-agg +run-agg: ## Runs the aggregator service + $(RUNAGGREGATOR) + +.PHONY: stop-agg +stop-agg: ## Stops the aggregator service + $(STOPAGGREGATOR) + +.PHONY: run-grafana +run-grafana: ## Runs the grafana service + $(RUNGRAFANA) + +.PHONY: stop-grafana +stop-grafana: ## Stops the grafana service + $(STOPGRAFANA) + +.PHONY: run-permissionless +run-permissionless: run-node ## Runs the trusted and permissionless node + $(RUNPERMISSIONLESSDB) + sleep 1 + $(RUNPERMISSIONLESSZKPROVER) + $(RUNPERMISSIONLESSNODE) + +.PHONY: stop-permissionless +stop-permissionless: stop-node## Stops the permissionless node + $(STOPPERMISSIONLESSNODE) + $(STOPPERMISSIONLESSZKPROVER) + $(STOPPERMISSIONLESSDB) + +.PHONY: run-approve-matic +run-approve-matic: ## Runs approve in node container + $(RUNAPPROVE) + +.PHONY: stop-approve-matic +stop-approve-matic: ## Stops approve in node container + $(STOPAPPROVE) + +.PHONY: run +run: ## Runs a full node + $(RUNSTATEDB) + $(RUNPOOLDB) + $(RUNEVENTDB) + $(RUNL1NETWORK) + sleep 1 + $(RUNZKPROVER) + $(RUNAPPROVE) + sleep 3 + $(RUNSYNC) + sleep 2 + $(RUNETHTXMANAGER) + $(RUNSEQUENCER) + $(RUNSEQUENCESENDER) + $(RUNL2GASPRICER) + $(RUNAGGREGATOR) + $(RUNJSONRPC) + +.PHONY: stop +stop: ## Stops all services + $(STOP) + +.PHONY: ship +ship: ## Builds docker images and run them + cd .. && make build-docker && cd ./test && make run + +.PHONY: reship +reship: stop ship ## Executes `make stop` and `make sail` commands + +.PHONY: restart +restart: stop run ## Executes `make stop` and `make run` commands + +.PHONY: run-metrics +run-metrics: ## Runs the metrics container + $(RUNMETRICS) + +.PHONY: stop-metrics +stop-metrics: ## Stops the metrics container + $(STOPMETRICS) + +.PHONY: init-network +init-network: ## Initializes the network + go run ./scripts/init_network/main.go . + +.PHONY: deploy-sc +deploy-sc: ## deploys some examples of transactions and smart contracts + go run ./scripts/deploy_sc/main.go . + +.PHONY: send-transfers +send-transfers: ## sends some ETH transfers txs to test the network + go run ./scripts/send_transfers/main.go . + +.PHONY: deploy-uniswap +deploy-uniswap: ## deploy the uniswap environment to the network + go run ./scripts/uniswap/main.go . + +.PHONY: run-db-scripts +run-db-scripts: ## Executes scripts on the db after it has been initialized, potentially using info from the environment + ./scripts/postgres/run.sh + +.PHONY: install-mockery +install-mockery: ## Installs mockery with the correct version to generate the mocks + go install github.com/vektra/mockery/v2@v2.22.1 + +.PHONY: generate-mocks +generate-mocks: ## Generates mocks for the tests, using mockery tool + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=storageInterface --dir=../jsonrpc --output=../jsonrpc --outpkg=jsonrpc --inpackage --structname=storageMock --filename=mock_storage.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=PoolInterface --dir=../jsonrpc/types --output=../jsonrpc/mocks --outpkg=mocks --structname=PoolMock --filename=mock_pool.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=StateInterface --dir=../jsonrpc/types --output=../jsonrpc/mocks --outpkg=mocks --structname=StateMock --filename=mock_state.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../jsonrpc/mocks --outpkg=mocks --structname=DBTxMock --filename=mock_dbtx.go + + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=workerInterface --dir=../sequencer --output=../sequencer --outpkg=sequencer --inpackage --structname=WorkerMock --filename=mock_worker.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=stateInterface --dir=../sequencer --output=../sequencer --outpkg=sequencer --inpackage --structname=StateMock --filename=mock_state.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=txPool --dir=../sequencer --output=../sequencer --outpkg=sequencer --inpackage --structname=PoolMock --filename=mock_pool.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../sequencer --outpkg=sequencer --structname=DbTxMock --filename=mock_dbtx.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=dbManagerInterface --dir=../sequencer --output=../sequencer --outpkg=sequencer --inpackage --structname=DbManagerMock --filename=mock_db_manager.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=etherman --dir=../sequencer --output=../sequencer --outpkg=sequencer --inpackage --structname=EthermanMock --filename=mock_etherman.go + + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=ethermanInterface --dir=../synchronizer --output=../synchronizer --outpkg=synchronizer --structname=ethermanMock --filename=mock_etherman.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=stateInterface --dir=../synchronizer --output=../synchronizer --outpkg=synchronizer --structname=stateMock --filename=mock_state.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=ethTxManager --dir=../synchronizer --output=../synchronizer --outpkg=synchronizer --structname=ethTxManagerMock --filename=mock_ethtxmanager.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=poolInterface --dir=../synchronizer --output=../synchronizer --outpkg=synchronizer --structname=poolMock --filename=mock_pool.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=zkEVMClientInterface --dir=../synchronizer --output=../synchronizer --outpkg=synchronizer --structname=zkEVMClientMock --filename=mock_zkevmclient.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../synchronizer --outpkg=synchronizer --structname=dbTxMock --filename=mock_dbtx.go + + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=GasPricer --srcpkg=github.com/ethereum/go-ethereum --output=../etherman --outpkg=etherman --structname=etherscanMock --filename=mock_etherscan.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=GasPricer --srcpkg=github.com/ethereum/go-ethereum --output=../etherman --outpkg=etherman --structname=ethGasStationMock --filename=mock_ethgasstation.go + + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=ethermanInterface --dir=../ethtxmanager --output=../ethtxmanager --outpkg=ethtxmanager --structname=ethermanMock --filename=mock_etherman_test.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=stateInterface --dir=../ethtxmanager --output=../ethtxmanager --outpkg=ethtxmanager --structname=stateMock --filename=mock_state_test.go + + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=pool --dir=../gasprice --output=../gasprice --outpkg=gasprice --structname=poolMock --filename=mock_pool.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=ethermanInterface --dir=../gasprice --output=../gasprice --outpkg=gasprice --structname=ethermanMock --filename=mock_etherman.go + + ## mocks for the aggregator tests + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=stateInterface --dir=../aggregator --output=../aggregator/mocks --outpkg=mocks --structname=StateMock --filename=mock_state.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=proverInterface --dir=../aggregator --output=../aggregator/mocks --outpkg=mocks --structname=ProverMock --filename=mock_prover.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=etherman --dir=../aggregator --output=../aggregator/mocks --outpkg=mocks --structname=Etherman --filename=mock_etherman.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=ethTxManager --dir=../aggregator --output=../aggregator/mocks --outpkg=mocks --structname=EthTxManager --filename=mock_ethtxmanager.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=aggregatorTxProfitabilityChecker --dir=../aggregator --output=../aggregator/mocks --outpkg=mocks --structname=ProfitabilityCheckerMock --filename=mock_profitabilitychecker.go + export "GOROOT=$$(go env GOROOT)" && $$(go env GOPATH)/bin/mockery --name=Tx --srcpkg=github.com/jackc/pgx/v4 --output=../aggregator/mocks --outpkg=mocks --structname=DbTxMock --filename=mock_dbtx.go + +.PHONY: run-benchmarks +run-benchmarks: run-db ## Runs benchmars + go test -bench=. ./state/tree + +.PHONY: compile-scs +compile-scs: ## Compiles smart contracts, configuration in test/contracts/index.yaml + go run ./scripts/cmd... compilesc --input ./contracts + +## Help display. +## Pulls comments from beside commands and prints a nicely formatted +## display with the commands and their usage information. +.DEFAULT_GOAL := help + +.PHONY: help +help: ## Prints this help + @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ + | sort \ + | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/test/aggregator.keystore b/test/aggregator.keystore new file mode 100644 index 0000000000..36adf8bc3f --- /dev/null +++ b/test/aggregator.keystore @@ -0,0 +1 @@ +{"version":3,"id":"71b028b6-9b1d-4f4c-9e66-31c94a6eb679","address":"70997970c51812dc3a010c7d01b50e0d17dc79c8","crypto":{"ciphertext":"985d5dc5f7750fc4ad0ad0d370486870016bb97e00ef1f7b146d6ad95d456861","cipherparams":{"iv":"f51b18b9f45872f71c3578513fca6cb0"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"6253e2d8a71e4808dd11143329cfea467cabb37ac1e1e55dbc0dd90ff22524a7","n":8192,"r":8,"p":1},"mac":"922f741e84201fc7c17bbf9fae5dba6c04a2a99a7268998b5a0268aa690004be"}} \ No newline at end of file diff --git a/test/benchmarks/interfaces.go b/test/benchmarks/interfaces.go deleted file mode 100644 index cb542eb196..0000000000 --- a/test/benchmarks/interfaces.go +++ /dev/null @@ -1,14 +0,0 @@ -package benchmarks - -import ( - "context" - - "github.com/jackc/pgx/v4" -) - -// Consumer interfaces required by the package. - -// stateInterface gathers the methods required to interact with the state. -type stateInterface interface { - GetLastL2BlockNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error) -} diff --git a/test/benchmarks/sequencer/common/metrics/metrics.go b/test/benchmarks/sequencer/common/metrics/metrics.go new file mode 100644 index 0000000000..4b825b8a9d --- /dev/null +++ b/test/benchmarks/sequencer/common/metrics/metrics.go @@ -0,0 +1,108 @@ +package metrics + +import ( + "fmt" + "net/http" + "os/exec" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + metricsLib "github.com/0xPolygonHermez/zkevm-node/metrics" + "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics" + metricsState "github.com/0xPolygonHermez/zkevm-node/state/metrics" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" +) + +const ( + oneHundred = 100 + profilingPort = 6060 +) + +// CalculateAndPrint calculates and prints the results +func CalculateAndPrint(prometheusResp *http.Response, profilingResult string, elapsed time.Duration, sequencerTimeSub, executorTimeSub float64, nTxs int) { + var ( + sequencerTime, executorTime, workerTime float64 + err error + ) + if prometheusResp != nil { + sequencerTime, executorTime, workerTime, err = GetValues(prometheusResp) + if err != nil { + log.Fatalf("error getting prometheus metrics: %v", err) + } + } + + log.Info("##########") + log.Info("# Result #") + log.Info("##########") + log.Infof("Total time (including setup of environment and starting containers): %v", elapsed) + + if prometheusResp != nil { + log.Info("######################") + log.Info("# Prometheus Metrics #") + log.Info("######################") + actualTotalTime := sequencerTime - sequencerTimeSub + actualExecutorTime := executorTime - executorTimeSub + PrintPrometheus(actualTotalTime, actualExecutorTime, workerTime) + log.Infof("[Transactions per second]: %v", float64(nTxs)/actualTotalTime) + } + if profilingResult != "" { + log.Info("#####################") + log.Info("# Profiling Metrics #") + log.Info("#####################") + log.Infof("%v", profilingResult) + } +} + +// PrintPrometheus prints the prometheus metrics +func PrintPrometheus(totalTime float64, executorTime float64, workerTime float64) { + log.Infof("[TOTAL Processing Time]: %v s", totalTime) + log.Infof("[EXECUTOR Processing Time]: %v s", executorTime) + log.Infof("[SEQUENCER Processing Time]: %v s", totalTime-executorTime) + log.Infof("[WORKER Processing Time]: %v s", workerTime) + log.Infof("[EXECUTOR Time Percentage from TOTAL]: %.2f %%", (executorTime/totalTime)*oneHundred) + log.Infof("[WORKER Time Percentage from TOTAL]: %.2f %%", (workerTime/totalTime)*oneHundred) +} + +// GetValues gets the prometheus metric values +func GetValues(metricsResponse *http.Response) (float64, float64, float64, error) { + var err error + if metricsResponse == nil { + metricsResponse, err = FetchPrometheus() + if err != nil { + log.Fatalf("error getting prometheus metrics: %v", err) + } + } + + mf, err := testutils.ParseMetricFamilies(metricsResponse.Body) + if err != nil { + return 0, 0, 0, err + } + sequencerTotalProcessingTimeHisto := mf[metrics.ProcessingTimeName].Metric[0].Histogram + sequencerTotalProcessingTime := sequencerTotalProcessingTimeHisto.GetSampleSum() + + workerTotalProcessingTimeHisto := mf[metrics.WorkerProcessingTimeName].Metric[0].Histogram + workerTotalProcessingTime := workerTotalProcessingTimeHisto.GetSampleSum() + + executorTotalProcessingTimeHisto := mf[metricsState.ExecutorProcessingTimeName].Metric[0].Histogram + executorTotalProcessingTime := executorTotalProcessingTimeHisto.GetSampleSum() + return sequencerTotalProcessingTime, executorTotalProcessingTime, workerTotalProcessingTime, nil +} + +// FetchPrometheus fetches the prometheus metrics +func FetchPrometheus() (*http.Response, error) { + log.Infof("Fetching prometheus metrics ...") + return http.Get(fmt.Sprintf("http://localhost:%d%s", params.PrometheusPort, metricsLib.Endpoint)) +} + +// FetchProfiling fetches the profiling metrics +func FetchProfiling() (string, error) { + fullUrl := fmt.Sprintf("http://localhost:%d%s", profilingPort, metricsLib.ProfileEndpoint) + log.Infof("Fetching profiling metrics from: %s ...", fullUrl) + cmd := exec.Command("go", "tool", "pprof", "-show=sequencer", "-top", fullUrl) + out, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("Error running pprof: %v\n%s", err, out) + } + return string(out), err +} diff --git a/test/benchmarks/sequencer/common/params/constants.go b/test/benchmarks/sequencer/common/params/constants.go new file mode 100644 index 0000000000..93aae94dcd --- /dev/null +++ b/test/benchmarks/sequencer/common/params/constants.go @@ -0,0 +1,16 @@ +package params + +import ( + "time" +) + +const ( + // DefaultDeadline is the default deadline for the sequencer + DefaultDeadline = 6000 * time.Second + // MaxCumulativeGasUsed is the maximum cumulative gas used + MaxCumulativeGasUsed = 80000000000 + // PrometheusPort is the port where prometheus is running + PrometheusPort = 9092 + // NumberOfTxs is the number of transactions to send + NumberOfTxs = 500 +) diff --git a/test/benchmarks/sequencer/common/params/variables.go b/test/benchmarks/sequencer/common/params/variables.go new file mode 100644 index 0000000000..9b12cbb930 --- /dev/null +++ b/test/benchmarks/sequencer/common/params/variables.go @@ -0,0 +1,30 @@ +package params + +import ( + "context" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/test/dbutils" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +var ( + // Ctx is the context + Ctx = context.Background() + // PoolDbConfig is the pool db config + PoolDbConfig = dbutils.NewPoolConfigFromEnv() + // SequencerPrivateKey is the private key of the sequencer + SequencerPrivateKey = operations.DefaultSequencerPrivateKey + // ChainID is the chain id + ChainID = operations.DefaultL2ChainID + // OpsCfg is the operations config + OpsCfg = operations.GetDefaultOperationsConfig() + // ToAddress is the address to send the txs + ToAddress = "0x4d5Cf5032B2a844602278b01199ED191A86c93ff" + // To is the address to send the txs + To = common.HexToAddress(ToAddress) + // PrivateKey is the private key of the sender + PrivateKey, _ = crypto.HexToECDSA(strings.TrimPrefix(SequencerPrivateKey, "0x")) +) diff --git a/test/benchmarks/sequencer/common/setup/setup.go b/test/benchmarks/sequencer/common/setup/setup.go new file mode 100644 index 0000000000..6cedd0fade --- /dev/null +++ b/test/benchmarks/sequencer/common/setup/setup.go @@ -0,0 +1,130 @@ +package setup + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/config/types" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const ( + sleepDuration = 5 * time.Second + minAllowedGasPriceIntervalMinutes = 5 + pollMinAllowedGasPriceIntervalSeconds = 15 +) + +// Environment sets up the environment for the benchmark +func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethclient.Client, *pool.Pool, *bind.TransactOpts) { + if testing.Short() { + b.Skip() + } + + err := operations.Teardown() + require.NoError(b, err) + + params.OpsCfg.State.MaxCumulativeGasUsed = params.MaxCumulativeGasUsed + opsman, err := operations.NewManager(ctx, params.OpsCfg) + require.NoError(b, err) + + err = Components(opsman) + require.NoError(b, err) + time.Sleep(sleepDuration) + + // Load account with balance on local genesis + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) + require.NoError(b, err) + + // Load params client + client, err := ethclient.Dial(operations.DefaultL2NetworkURL) + require.NoError(b, err) + + st := opsman.State() + s, err := pgpoolstorage.NewPostgresPoolStorage(params.PoolDbConfig) + require.NoError(b, err) + config := pool.Config{ + DB: params.PoolDbConfig, + MinAllowedGasPriceInterval: types.NewDuration(minAllowedGasPriceIntervalMinutes * time.Minute), + PollMinAllowedGasPriceInterval: types.NewDuration(pollMinAllowedGasPriceIntervalSeconds * time.Second), + } + + eventStorage, err := nileventstorage.NewNilEventStorage() + require.NoError(b, err) + eventLog := event.NewEventLog(event.Config{}, eventStorage) + + pl := pool.NewPool(config, s, st, common.Address{}, params.ChainID, eventLog) + + // Print Info before send + senderBalance, err := client.BalanceAt(ctx, auth.From, nil) + require.NoError(b, err) + senderNonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(b, err) + + // Print Initial Stats + log.Infof("Receiver Addr: %v", params.To.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", senderNonce) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(b, err) + + // PrivateKey is the private key of the sender + // Auth is the auth of the sender + auth, err = bind.NewKeyedTransactorWithChainID(params.PrivateKey, new(big.Int).SetUint64(params.ChainID)) + if err != nil { + panic(err) + } + auth.GasPrice = gasPrice + auth.Nonce = new(big.Int).SetUint64(senderNonce) + + return opsman, client, pl, auth +} + +// Components runs the network container, starts synchronizer and JSON-RPC components, and approves matic +func Components(opsman *operations.Manager) error { + // Run network container + err := opsman.StartNetwork() + if err != nil { + return err + } + + // Approve matic + err = operations.ApproveMatic() + if err != nil { + return err + } + + err = operations.StartComponent("sync") + if err != nil { + return err + } + + err = operations.StartComponent("json-rpc") + if err != nil { + return err + } + time.Sleep(sleepDuration) + + return nil +} + +// BootstrapSequencer starts the sequencer and waits for it to be ready +func BootstrapSequencer(b *testing.B, opsman *operations.Manager) { + log.Debug("Starting sequencer ....") + err := operations.StartComponent("seq") + require.NoError(b, err) + log.Debug("Sequencer Started!") +} diff --git a/test/benchmarks/sequencer/common/transactions/transactions.go b/test/benchmarks/sequencer/common/transactions/transactions.go new file mode 100644 index 0000000000..4ebda4ccc3 --- /dev/null +++ b/test/benchmarks/sequencer/common/transactions/transactions.go @@ -0,0 +1,105 @@ +package transactions + +import ( + "context" + "math/big" + "strconv" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/ethclient" +) + +// SendAndWait sends a number of transactions and waits for them to be marked as pending in the pool +func SendAndWait( + ctx context.Context, + auth *bind.TransactOpts, + client *ethclient.Client, + countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), + nTxs int, + erc20SC *ERC20.ERC20, + txSenderFunc func(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts, erc20SC *ERC20.ERC20) error, +) error { + auth.GasLimit = 2100000 + log.Debugf("Sending %d txs ...", nTxs) + startingNonce := auth.Nonce.Uint64() + maxNonce := uint64(nTxs) + startingNonce + initialPendingCount, err := countByStatusFunc(params.Ctx, pool.TxStatusPending) + if err != nil { + panic(err) + } + + for nonce := startingNonce; nonce < maxNonce; nonce++ { + err = txSenderFunc(client, auth.GasPrice, nonce, auth, erc20SC) + if err != nil { + for err != nil && err.Error() == "nonce intrinsic error" { + log.Warnf("nonce intrinsic error, retrying with nonce %d", nonce) + err = txSenderFunc(client, auth.GasPrice, nonce, auth, erc20SC) + } + if err == nil { + continue + } + return err + } + } + log.Debug("All txs were sent!") + log.Debug("Waiting pending transactions To be added in the pool ...") + err = operations.Poll(1*time.Second, params.DefaultDeadline, func() (bool, error) { + // using a closure here To capture st and currentBatchNumber + count, err := countByStatusFunc(ctx, pool.TxStatusPending) + if err != nil { + return false, err + } + + log.Debugf("amount of pending txs: %d\n", count) + done := count-initialPendingCount <= 0 + return done, nil + }) + if err != nil { + return err + } + + log.Debug("All pending txs are added in the pool!") + + return nil +} + +// WaitStatusSelected waits for a number of transactions to be marked as selected in the pool +func WaitStatusSelected(countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), initialCount uint64, nTxs uint64) error { + log.Debug("Wait for sequencer to select all txs from the pool") + pollingInterval := 1 * time.Second + + prevCount := uint64(0) + txsPerSecond := 0 + txsPerSecondAsStr := "N/A" + estimatedTimeToFinish := "N/A" + err := operations.Poll(pollingInterval, params.DefaultDeadline, func() (bool, error) { + selectedCount, err := countByStatusFunc(params.Ctx, pool.TxStatusSelected) + if err != nil { + return false, err + } + currCount := selectedCount - initialCount + remainingTxs := nTxs - currCount + if prevCount > 0 { + txsPerSecond = int(currCount - prevCount) + if txsPerSecond == 0 { + estimatedTimeToFinish = "N/A" + } else { + estimatedTimeToFinish = (time.Duration(int(remainingTxs)/txsPerSecond) * time.Second).String() + } + txsPerSecondAsStr = strconv.Itoa(txsPerSecond) + } + log.Debugf("amount of selected txs: %d/%d, estimated txs per second: %s, time to finish: %s", selectedCount-initialCount, nTxs, txsPerSecondAsStr, estimatedTimeToFinish) + prevCount = currCount + + done := (int64(selectedCount) - int64(initialCount)) >= int64(nTxs) + return done, nil + }) + + return err +} diff --git a/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go new file mode 100644 index 0000000000..cfbc6446ac --- /dev/null +++ b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go @@ -0,0 +1,97 @@ +package erc20_transfers + +import ( + "context" + "fmt" + "math/big" + "net/http" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const ( + txTimeout = 60 * time.Second + profilingEnabled = false +) + +var ( + erc20SC *ERC20.ERC20 +) + +func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { + start := time.Now() + opsman, client, pl, auth := setup.Environment(params.Ctx, b) + setup.BootstrapSequencer(b, opsman) + startDeploySCTime := time.Now() + err := deployERC20Contract(b, client, params.Ctx, auth) + require.NoError(b, err) + deploySCElapsed := time.Since(startDeploySCTime) + deploySCSequencerTime, deploySCExecutorOnlyTime, _, err := metrics.GetValues(nil) + if err != nil { + return + } + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + require.NoError(b, err) + err = transactions.SendAndWait(params.Ctx, auth, client, pl.CountTransactionsByStatus, params.NumberOfTxs, erc20SC, TxSender) + require.NoError(b, err) + + var ( + elapsed time.Duration + response *http.Response + ) + + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", params.NumberOfTxs), func(b *testing.B) { + // Wait all txs to be selected by the sequencer + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) + require.NoError(b, err) + elapsed = time.Since(start) + log.Infof("Total elapsed time: %s", elapsed) + response, err = metrics.FetchPrometheus() + require.NoError(b, err) + }) + + var profilingResult string + if profilingEnabled { + profilingResult, err = metrics.FetchProfiling() + require.NoError(b, err) + } + + metrics.CalculateAndPrint(response, profilingResult, elapsed-deploySCElapsed, deploySCSequencerTime, deploySCExecutorOnlyTime, params.NumberOfTxs) + log.Infof("########################################") + log.Infof("# Deploying ERC20 SC and Mint Tx took: #") + log.Infof("########################################") + metrics.PrintPrometheus(deploySCSequencerTime, deploySCExecutorOnlyTime, 0) +} + +func deployERC20Contract(b *testing.B, client *ethclient.Client, ctx context.Context, auth *bind.TransactOpts) error { + var ( + tx *types.Transaction + err error + ) + log.Debugf("Sending TX to deploy ERC20 SC") + _, tx, erc20SC, err = ERC20.DeployERC20(auth, client, "Test Coin", "TCO") + require.NoError(b, err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + require.NoError(b, err) + log.Debugf("Sending TX to do a ERC20 mint") + auth.Nonce = big.NewInt(1) // for the mint tx + tx, err = erc20SC.Mint(auth, mintAmountBig) + auth.Nonce = big.NewInt(2) + require.NoError(b, err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + require.NoError(b, err) + return err +} diff --git a/test/benchmarks/sequencer/erc20-transfers/tx_sender.go b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go new file mode 100644 index 0000000000..d0e3faa626 --- /dev/null +++ b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go @@ -0,0 +1,40 @@ +package erc20_transfers + +import ( + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/ethclient" +) + +const ( + mintAmount = 1000000000000000000 + transferAmount = 0 +) + +var ( + mintAmountBig = big.NewInt(mintAmount) + transferAmountBig = big.NewInt(transferAmount) + countTxs = 0 +) + +// TxSender sends ERC20 transfer to the sequencer +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts, erc20SC *ERC20.ERC20) error { + log.Debugf("sending tx num: %d nonce: %d", countTxs, nonce) + auth.Nonce = new(big.Int).SetUint64(nonce) + var actualTransferAmount *big.Int + if nonce%2 == 0 { + actualTransferAmount = big.NewInt(0).Sub(transferAmountBig, auth.Nonce) + } else { + actualTransferAmount = big.NewInt(0).Add(transferAmountBig, auth.Nonce) + } + _, err := erc20SC.Transfer(auth, params.To, actualTransferAmount) + if err == nil { + countTxs += 1 + } + + return err +} diff --git a/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go new file mode 100644 index 0000000000..129cb851ee --- /dev/null +++ b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go @@ -0,0 +1,54 @@ +package eth_transfers + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + "github.com/stretchr/testify/require" +) + +const ( + profilingEnabled = false +) + +func BenchmarkSequencerEthTransfersPoolProcess(b *testing.B) { + start := time.Now() + //defer func() { require.NoError(b, operations.Teardown()) }() + opsman, client, pl, auth := setup.Environment(params.Ctx, b) + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + require.NoError(b, err) + setup.BootstrapSequencer(b, opsman) + err = transactions.SendAndWait(params.Ctx, auth, client, pl.CountTransactionsByStatus, params.NumberOfTxs, nil, TxSender) + require.NoError(b, err) + + var ( + elapsed time.Duration + prometheusResponse *http.Response + ) + + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", params.NumberOfTxs), func(b *testing.B) { + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) + require.NoError(b, err) + elapsed = time.Since(start) + log.Infof("Total elapsed time: %s", elapsed) + prometheusResponse, err = metrics.FetchPrometheus() + require.NoError(b, err) + }) + + var profilingResult string + if profilingEnabled { + profilingResult, err = metrics.FetchProfiling() + require.NoError(b, err) + } + + metrics.CalculateAndPrint(prometheusResponse, profilingResult, elapsed, 0, 0, params.NumberOfTxs) + fmt.Printf("%s\n", profilingResult) +} diff --git a/test/benchmarks/sequencer/eth-transfers/tx_sender.go b/test/benchmarks/sequencer/eth-transfers/tx_sender.go new file mode 100644 index 0000000000..02ac3f6c8b --- /dev/null +++ b/test/benchmarks/sequencer/eth-transfers/tx_sender.go @@ -0,0 +1,47 @@ +package eth_transfers + +import ( + "errors" + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + gasLimit = 21000 + ethAmount = big.NewInt(0) + sleepTime = 5 * time.Second + countTxs = 0 +) + +// TxSender sends eth transfer to the sequencer +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts, erc20SC *ERC20.ERC20) error { + log.Debugf("sending tx num: %d nonce: %d", countTxs, nonce) + auth.Nonce = big.NewInt(int64(nonce)) + tx := types.NewTransaction(nonce, params.To, ethAmount, uint64(gasLimit), gasPrice, nil) + signedTx, err := auth.Signer(auth.From, tx) + if err != nil { + return err + } + + err = l2Client.SendTransaction(params.Ctx, signedTx) + if errors.Is(err, state.ErrStateNotSynchronized) { + for errors.Is(err, state.ErrStateNotSynchronized) { + time.Sleep(sleepTime) + err = l2Client.SendTransaction(params.Ctx, signedTx) + } + } + + if err == nil { + countTxs += 1 + } + + return err +} diff --git a/test/benchmarks/sequencer/scripts/common/environment/constants.go b/test/benchmarks/sequencer/scripts/common/environment/constants.go new file mode 100644 index 0000000000..13a002519c --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/environment/constants.go @@ -0,0 +1,35 @@ +package environment + +import ( + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" +) + +var ( + // IntBase is the base for the conversion of strings to integers + IntBase = 10 + // PrivateKey is the private key of the sequencer + PrivateKey = testutils.GetEnv("PRIVATE_KEY", operations.DefaultSequencerPrivateKey) + // L2ChainId is the chain id of the L2 network + L2ChainId = testutils.GetEnv("CHAIN_ID", strconv.FormatUint(operations.DefaultL2ChainID, IntBase)) + //Erc20TokenAddress is the address of the ERC20 token + Erc20TokenAddress = testutils.GetEnv("ERC20_TOKEN_ADDRESS", "0x729fc461b26f69cf75a31182788eaf722b08c240") + + l2NetworkRPCURL = testutils.GetEnv("L2_NETWORK_RPC_URL", operations.DefaultL2NetworkURL) + + // StateDB Credentials + stateDbName = testutils.GetEnv("STATE_DB_NAME", "state_db") + stateDbUser = testutils.GetEnv("STATE_DB_USER", "state_user") + stateDbPass = testutils.GetEnv("STATE_DB_PASS", "state_password") + stateDbHost = testutils.GetEnv("STATE_DB_HOST", "localhost") + stateDbPort = testutils.GetEnv("STATE_DB_PORT", "5432") + + // PoolDB Credentials + poolDbName = testutils.GetEnv("POOL_DB_NAME", "pool_db") + poolDbUser = testutils.GetEnv("POOL_DB_USER", "pool_user") + poolDbPass = testutils.GetEnv("POOL_DB_PASS", "pool_password") + poolDbHost = testutils.GetEnv("POOL_DB_HOST", "localhost") + poolDbPort = testutils.GetEnv("POOL_DB_PORT", "5433") +) diff --git a/test/benchmarks/sequencer/scripts/common/environment/init.go b/test/benchmarks/sequencer/scripts/common/environment/init.go new file mode 100644 index 0000000000..3d13a28663 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/environment/init.go @@ -0,0 +1,97 @@ +package environment + +import ( + "context" + "math/big" + "strconv" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + maxConnections = 10 + bitSize = 64 +) + +// Init sets up the environment for the benchmark +func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *state.PostgresStorage, *ethclient.Client, *bind.TransactOpts) { + ctx := context.Background() + pl, err := pgpoolstorage.NewPostgresPoolStorage(db.Config{ + Name: poolDbName, + User: poolDbUser, + Password: poolDbPass, + Host: poolDbHost, + Port: poolDbPort, + EnableLog: false, + MaxConns: maxConnections, + }) + if err != nil { + panic(err) + } + + l2Client, err := ethclient.Dial(l2NetworkRPCURL) + if err != nil { + panic(err) + } + // PrivateKey is the private key of the sender + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(PrivateKey, "0x")) + if err != nil { + panic(err) + } + chainId, err := strconv.ParseUint(L2ChainId, IntBase, bitSize) + if err != nil { + panic(err) + } + log.Infof("L2ChainId: %d", chainId) + // Auth is the auth of the sender + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, new(big.Int).SetUint64(chainId)) + if err != nil { + panic(err) + } + // Print Info before send + senderBalance, err := l2Client.BalanceAt(ctx, auth.From, nil) + if err != nil { + panic(err) + } + senderNonce, err := l2Client.PendingNonceAt(ctx, auth.From) + if err != nil { + panic(err) + } + + // Print Initial Stats + log.Infof("Receiver Addr: %v", params.To.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", senderNonce) + + gasPrice, err := l2Client.SuggestGasPrice(ctx) + if err != nil { + panic(err) + } + auth.GasPrice = gasPrice + stateDbCfg := db.Config{ + User: stateDbUser, + Password: stateDbPass, + Name: stateDbName, + Host: stateDbHost, + Port: stateDbPort, + EnableLog: true, + MaxConns: maxConnections, + } + stateDb, err := db.NewSQLDB(stateDbCfg) + if err != nil { + panic(err) + } + stateStorage := state.NewPostgresStorage(stateDb) + auth.Nonce = new(big.Int).SetUint64(senderNonce) + + return ctx, pl, stateStorage, l2Client, auth +} diff --git a/test/benchmarks/sequencer/scripts/common/results/print.go b/test/benchmarks/sequencer/scripts/common/results/print.go new file mode 100644 index 0000000000..abee515213 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/results/print.go @@ -0,0 +1,19 @@ +package results + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" +) + +// Print prints the results of the benchmark +func Print(elapsed time.Duration) { + // Print results + log.Info("##########") + log.Info("# Result #") + log.Info("##########") + log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + log.Infof("Number of txs sent: %d", params.NumberOfTxs) + log.Infof("Txs per second: %f", float64(params.NumberOfTxs)/elapsed.Seconds()) +} diff --git a/test/benchmarks/sequencer/scripts/erc20-transfers/main.go b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go new file mode 100644 index 0000000000..c05f549649 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + erc20transfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/erc20-transfers" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/environment" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/results" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/ethereum/go-ethereum/common" +) + +func main() { + var ( + err error + ) + ctx, pl, state, l2Client, auth := environment.Init() + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + if err != nil { + panic(err) + } + + start := time.Now() + erc20SC, err := ERC20.NewERC20(common.HexToAddress(environment.Erc20TokenAddress), l2Client) + if err != nil { + panic(err) + } + // Send Txs + err = transactions.SendAndWait( + ctx, + auth, + l2Client, + pl.CountTransactionsByStatus, + params.NumberOfTxs, + erc20SC, + erc20transfers.TxSender, + ) + if err != nil { + panic(err) + } + + // Wait for Txs to be selected + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) + if err != nil { + panic(err) + } + + lastL2BlockTimestamp, err := state.GetLastL2BlockCreatedAt(params.Ctx, nil) + if err != nil { + panic(err) + } + elapsed := lastL2BlockTimestamp.Sub(start) + results.Print(elapsed) +} diff --git a/test/benchmarks/sequencer/scripts/eth-transfers/main.go b/test/benchmarks/sequencer/scripts/eth-transfers/main.go new file mode 100644 index 0000000000..9705a5a234 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/eth-transfers/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + ethtransfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/eth-transfers" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/environment" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/results" +) + +func main() { + var ( + err error + ) + ctx, pl, state, l2Client, auth := environment.Init() + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + if err != nil { + panic(err) + } + + start := time.Now() + // Send Txs + err = transactions.SendAndWait( + ctx, + auth, + l2Client, + pl.CountTransactionsByStatus, + params.NumberOfTxs, + nil, + ethtransfers.TxSender, + ) + if err != nil { + panic(err) + } + + // Wait for Txs to be selected + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) + if err != nil { + panic(err) + } + + lastL2BlockTimestamp, err := state.GetLastL2BlockCreatedAt(params.Ctx, nil) + if err != nil { + panic(err) + } + elapsed := lastL2BlockTimestamp.Sub(start) + results.Print(elapsed) +} diff --git a/test/benchmarks/sequencer_test.go b/test/benchmarks/sequencer_test.go deleted file mode 100644 index 6964f19106..0000000000 --- a/test/benchmarks/sequencer_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package benchmarks - -import ( - "context" - "fmt" - "math/big" - "strings" - "testing" - "time" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/dbutils" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "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/stretchr/testify/require" -) - -const ( - l1NetworkURL = "http://localhost:8545" - l2NetworkURL = "http://localhost:8123" - - defaultInterval = 10 * time.Second - defaultDeadline = 6000 * time.Second - - gasLimit = 21000 -) - -var dbConfig = dbutils.NewStateConfigFromEnv() - -var ( - ctx = context.Background() - sequencerPrivateKey = "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" - chainID = uint64(1000) - opsCfg = &operations.Config{ - State: &state.Config{ - MaxCumulativeGasUsed: 800000, - }, - - Sequencer: &operations.SequencerConfig{ - Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - PrivateKey: sequencerPrivateKey, - }, - } - - genAccBalance1, _ = new(big.Int).SetString("100000000000000000000", 10) - genAccBalance2, _ = new(big.Int).SetString("200000000000000000000", 10) - genAccAddr1 = "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D" - genAccAddr2 = "0x4d5Cf5032B2a844602278b01199ED191A86c93ff" - - genesisAccounts = map[string]big.Int{ - genAccAddr1: *genAccBalance1, - genAccAddr2: *genAccBalance2, - } - - ethAmount, _ = big.NewInt(0).SetString("100000000000", encoding.Base10) - privateKey, _ = crypto.HexToECDSA(strings.TrimPrefix(sequencerPrivateKey, "0x")) - auth, _ = bind.NewKeyedTransactorWithChainID(privateKey, new(big.Int).SetUint64(chainID)) - - table = []struct { - input int - }{ - {input: 100}, - {input: 1000}, - {input: 10000}, - {input: 100000}, - } -) - -func BenchmarkSequencer(b *testing.B) { - if testing.Short() { - b.Skip() - } - - for _, v := range table { - st, pl, gasPrice, l2Client := setUpEnv(b) - b.Run(fmt.Sprintf("amount_of_txs_%d", v.input), func(b *testing.B) { - for i := 0; i < b.N; i++ { - runTxSender(b, l2Client, pl, gasPrice, v.input) - } - }) - tearDownEnv(b, st) - } -} - -func setUpEnv(b *testing.B) (*state.State, *pool.Pool, *big.Int, *ethclient.Client) { - opsman, err := operations.NewManager(ctx, opsCfg) - require.NoError(b, err) - - st := opsman.State() - s, err := pgpoolstorage.NewPostgresPoolStorage(dbConfig) - require.NoError(b, err) - pl := pool.NewPool(s, st, common.Address{}, chainID) - // store current batch number to check later when the state is updated - require.NoError(b, opsman.SetGenesis(genesisAccounts)) - require.NoError(b, opsman.Setup()) - - // Eth client - client, err := ethclient.Dial(l1NetworkURL) - require.NoError(b, err) - - gasPrice, err := client.SuggestGasPrice(ctx) - require.NoError(b, err) - - l2Client, err := ethclient.Dial(l2NetworkURL) - require.NoError(b, err) - - return st, pl, gasPrice, l2Client -} - -func tearDownEnv(b *testing.B, st stateInterface) { - lastBatchNumber, err := st.GetLastL2BlockNumber(ctx, nil) - require.NoError(b, err) - fmt.Printf("lastBatchNumber: %v\n", lastBatchNumber) - require.NoError(b, operations.Teardown()) -} - -func runTxSender(b *testing.B, l2Client *ethclient.Client, pl *pool.Pool, gasPrice *big.Int, txsAmount int) { - var err error - for i := 0; i < txsAmount; i++ { - tx := types.NewTransaction(uint64(i), common.HexToAddress(genAccAddr2), ethAmount, gasLimit, gasPrice, nil) - signedTx, err := auth.Signer(auth.From, tx) - require.NoError(b, err) - err = l2Client.SendTransaction(ctx, signedTx) - require.NoError(b, err) - } - - // Wait for sequencer to select txs from pool and propose a new batch - // Wait for the synchronizer to update state - err = operations.Poll(defaultInterval, defaultDeadline, func() (bool, error) { - // using a closure here to capture st and currentBatchNumber - count, err := pl.CountPendingTransactions(ctx) - if err != nil { - return false, err - } - - fmt.Printf("amount of pending txs: %v\n", count) - done := count == 0 - return done, nil - }) - require.NoError(b, err) -} diff --git a/test/config/config.test.toml b/test/config/config.test.toml deleted file mode 100644 index 35a7ae193a..0000000000 --- a/test/config/config.test.toml +++ /dev/null @@ -1,106 +0,0 @@ -IsTrustedSequencer = true - -[Log] -Level = "debug" -Outputs = ["stdout"] - -[StateDB] -User = "state_user" -Password = "state_password" -Name = "state_db" -Host = "zkevm-state-db" -Port = "5432" -EnableLog = false -MaxConns = 200 - -[PoolDB] -User = "pool_user" -Password = "pool_password" -Name = "pool_db" -Host = "zkevm-pool-db" -Port = "5432" -EnableLog = false -MaxConns = 200 - -[Etherman] -URL = "http://zkevm-mock-l1-network:8545" -PrivateKeyPath = "./test/test.keystore" -PrivateKeyPassword = "testonly" - -[EthTxManager] -MaxSendBatchTxRetries = 10 -MaxVerifyBatchTxRetries = 10 -FrequencyForResendingFailedSendBatches = "1s" -FrequencyForResendingFailedVerifyBatch = "1s" -WaitTxToBeMined = "2m" -PercentageToIncreaseGasPrice = 10 -PercentageToIncreaseGasLimit = 10 - -[RPC] -Host = "0.0.0.0" -Port = 8123 -MaxRequestsPerIPAndSecond = 5000 -SequencerNodeURI = "" -BroadcastURI = "127.0.0.1:61090" -DefaultSenderAddress = "0x1111111111111111111111111111111111111111" - [RPC.DB] - User = "rpc_user" - Password = "rpc_password" - Name = "rpc_db" - Host = "zkevm-rpc-db" - Port = "5432" - EnableLog = false - MaxConns = 10 - -[Synchronizer] -SyncInterval = "1s" -SyncChunkSize = 100 -TrustedSequencerURI = "" - -[Sequencer] -MaxSequenceSize = "2000000" -WaitPeriodPoolIsEmpty = "1s" -WaitPeriodSendSequence = "15s" -LastBatchVirtualizationTimeMaxWaitPeriod = "10s" -WaitBlocksToUpdateGER = 10 -MaxTimeForBatchToBeOpen = "15s" -BlocksAmountForTxsToBeDeleted = 100 -FrequencyToCheckTxsForDelete = "12h" -MaxCumulativeGasUsed = 30000000 -MaxKeccakHashes = 468 -MaxPoseidonHashes = 279620 -MaxPoseidonPaddings = 149796 -MaxMemAligns = 262144 -MaxArithmetics = 262144 -MaxBinaries = 262144 -MaxSteps = 8388608 - [Sequencer.ProfitabilityChecker] - SendBatchesEvenWhenNotProfitable = "true" - -[Aggregator] -IntervalToConsolidateState = "1s" -IntervalFrequencyToGetProofGenerationState = "100ms" -TxProfitabilityCheckerType = "acceptall" -TxProfitabilityMinReward = "1.1" - -[GasPriceEstimator] -Type = "default" -DefaultGasPriceWei = 1000000000 - -[Provers] -ProverURIs = ["zkevm-prover:50052"] - -[MTServer] -Host = "0.0.0.0" -Port = 50060 -StoreBackend = "PostgreSQL" - -[MTClient] -URI = "zkevm-prover:50061" - -[Executor] -URI = "zkevm-prover:50071" - -[BroadcastServer] -Host = "0.0.0.0" -Port = 61090 diff --git a/test/config/debug.node.config.toml b/test/config/debug.node.config.toml new file mode 100644 index 0000000000..45a78bb43f --- /dev/null +++ b/test/config/debug.node.config.toml @@ -0,0 +1,152 @@ +IsTrustedSequencer = true + +[Log] +Environment = "development" # "production" or "development" +Level = "debug" +Outputs = ["stderr"] + +[StateDB] +User = "state_user" +Password = "state_password" +Name = "state_db" +Host = "localhost" +Port = "5432" +EnableLog = true +MaxConns = 10 + +[Pool] +FreeClaimGasLimit = 1500000 +IntervalToRefreshBlockedAddresses = "5m" +MaxTxBytesSize=30132 +MaxTxDataBytesSize=30000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "localhost" + Port = "5433" + EnableLog = false + MaxConns = 10 + +[Etherman] +URL = "http://localhost:8545" +MultiGasProvider = false + [Etherman.Etherscan] + ApiKey = "" + +[RPC] +Host = "0.0.0.0" +Port = 8123 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 10000 +SequencerNodeURI = "" +EnableL2SuggestedGasPricePolling = true + [RPC.WebSockets] + Enabled = true + Port = 8133 + +[Synchronizer] +SyncInterval = "5s" +SyncChunkSize = 100 +TrustedSequencerURL = "" + +[Sequencer] +WaitPeriodPoolIsEmpty = "1s" +BlocksAmountForTxsToBeDeleted = 100 +FrequencyToCheckTxsForDelete = "12h" +MaxTxsPerBatch = 150 +MaxBatchBytesSize = 129848 +MaxCumulativeGasUsed = 30000000 +MaxKeccakHashes = 468 +MaxPoseidonHashes = 279620 +MaxPoseidonPaddings = 149796 +MaxMemAligns = 262144 +MaxArithmetics = 262144 +MaxBinaries = 262144 +MaxSteps = 8388608 +WeightBatchBytesSize = 1 +WeightCumulativeGasUsed = 1 +WeightKeccakHashes = 1 +WeightPoseidonHashes = 1 +WeightPoseidonPaddings = 1 +WeightMemAligns = 1 +WeightArithmetics = 1 +WeightBinaries = 1 +WeightSteps = 1 +TxLifetimeCheckTimeout = "10m" +MaxTxLifetime = "3h" + [Sequencer.Finalizer] + GERDeadlineTimeout = "1s" + ForcedBatchDeadlineTimeout = "1s" + SleepDuration = "100ms" + ResourcePercentageToCloseBatch = 10 + GERFinalityNumberOfBlocks = 0 + ClosingSignalsManagerWaitForCheckingL1Timeout = "10s" + ClosingSignalsManagerWaitForCheckingGER = "10s" + ClosingSignalsManagerWaitForCheckingForcedBatches = "10s" + ForcedBatchesFinalityNumberOfBlocks = 0 + TimestampResolution = "10s" + [Sequencer.DBManager] + PoolRetrievalInterval = "500ms" + L2ReorgRetrievalInterval = "5s" + [Sequencer.Worker] + ResourceCostMultiplier = 1000 + +[SequenceSender] +WaitPeriodSendSequence = "15s" +LastBatchVirtualizationTimeMaxWaitPeriod = "10s" +MaxTxSizeForL1 = 131072 +SenderAddress = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +PrivateKeys = [{Path = "./test/sequencer.keystore", Password = "testonly"}] + +[Aggregator] +Host = "0.0.0.0" +Port = 50081 +ForkId = 2 +RetryTime = "5s" +VerifyProofInterval = "30s" +TxProfitabilityCheckerType = "acceptall" +TxProfitabilityMinReward = "1.1" +ProofStatePollingInterval = "5s" +SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +CleanupLockedProofsInterval = "2m" +GeneratingProofCleanupThreshold = "10m" + +[EthTxManager] +ForcedGas = 0 +PrivateKeys = [ + {Path = "../test/sequencer.keystore", Password = "testonly"}, + {Path = "../test/aggregator.keystore", Password = "testonly"} +] + +[L2GasPriceSuggester] +Type = "default" +DefaultGasPriceWei = 1000000000 + +[MTClient] +URI = "127.0.0.1:50061" + +[Executor] +URI = "127.0.0.1:50071" + +[Metrics] +Host = "0.0.0.0" +Port = 9091 +Enabled = false +ProfilingHost = "0.0.0.0" +ProfilingPort = 6060 +ProfilingEnabled = false + +[EventLog] + [EventLog.DB] + User = "event_user" + Password = "event_password" + Name = "event_db" + Host = "localhost" + Port = "5435" + EnableLog = false + MaxConns = 200 diff --git a/test/config/grafana/dashboard-dockers.json b/test/config/grafana/dashboard-dockers.json new file mode 100644 index 0000000000..555a5c09a4 --- /dev/null +++ b/test/config/grafana/dashboard-dockers.json @@ -0,0 +1,629 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [ + { + "params": [ + "$__interval", + "none" + ], + "type": "time" + } + ], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroupAlias(\"time\",$__interval),\n avg(usage_percent) AS \"cpu\",\n container_name as docker\nFROM docker_container_cpu\nWHERE\n $__timeFilter(\"time\") AND\n container_name in($docker)\nGROUP BY time, container_name\nORDER BY time ASC", + "refId": "A", + "select": [ + [ + { + "params": [ + "usage_percent" + ], + "type": "column" + }, + { + "params": [ + "avg" + ], + "type": "aggregate" + }, + { + "params": [ + "l" + ], + "type": "alias" + } + ] + ], + "table": "docker_container_cpu", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + }, + { + "datatype": "text", + "name": "", + "params": [ + "container_name", + "=", + "'$docker'" + ], + "type": "expression" + } + ] + } + ], + "title": "CPU", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n avg(usage_percent) AS \"mem\",\n container_name as docker\nFROM docker_container_mem\nWHERE\n $__timeFilter(\"time\") AND container_name in($docker)\nGROUP BY time, container_name\nORDER BY time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "usage_percent" + ], + "type": "column" + }, + { + "params": [ + "avg" + ], + "type": "aggregate" + }, + { + "params": [ + "l" + ], + "type": "alias" + } + ] + ], + "table": "docker_container_mem", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "MEM", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n avg(tx_bytes) - lag(avg(tx_bytes)) OVER (PARTITION BY container_name ORDER BY \"time\") AS \"tx_bytes\",\n -1 * (avg(rx_bytes) - lag(avg(rx_bytes)) OVER (PARTITION BY container_name ORDER BY \"time\")) AS \"rx_bytes\",\n container_name as docker\nFROM docker_container_net\nWHERE\n $__timeFilter(\"time\") AND container_name in($docker)\nGROUP BY time, container_name\nORDER BY time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "usage_percent" + ], + "type": "column" + }, + { + "params": [ + "avg" + ], + "type": "aggregate" + }, + { + "params": [ + "delta" + ], + "type": "window" + }, + { + "params": [ + "l" + ], + "type": "alias" + } + ] + ], + "table": "docker_container_mem", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "NET", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n avg(io_service_bytes_recursive_read) - lag(avg(io_service_bytes_recursive_read)) OVER (PARTITION BY container_name ORDER BY \"time\") AS \"read\",\n -1 * (avg(io_service_bytes_recursive_write) - lag(avg(io_service_bytes_recursive_write)) OVER (PARTITION BY container_name ORDER BY \"time\")) AS \"write\",\n container_name as docker\nFROM docker_container_blkio\nWHERE\n $__timeFilter(\"time\") AND container_name in($docker)\nGROUP BY time, container_name\nORDER BY time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "usage_percent" + ], + "type": "column" + }, + { + "params": [ + "avg" + ], + "type": "aggregate" + }, + { + "params": [ + "delta" + ], + "type": "window" + }, + { + "params": [ + "l" + ], + "type": "alias" + } + ] + ], + "table": "docker_container_mem", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "DISK", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": [ + "zkevm-json-rpc", + "zkevm-pool-db", + "zkevm-sequencer" + ], + "value": [ + "zkevm-json-rpc", + "zkevm-pool-db", + "zkevm-sequencer" + ] + }, + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "definition": "select distinct(container_name) from docker_container_cpu", + "hide": 0, + "includeAll": true, + "label": "docker", + "multi": true, + "name": "docker", + "options": [], + "query": "select distinct(container_name) from docker_container_cpu", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-2h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "browser", + "title": "Dockers", + "uid": "FBW3SsdVk", + "version": 1, + "weekStart": "monday" +} \ No newline at end of file diff --git a/test/config/grafana/dashboard-node.json b/test/config/grafana/dashboard-node.json new file mode 100644 index 0000000000..e7df006e6f --- /dev/null +++ b/test/config/grafana/dashboard-node.json @@ -0,0 +1,389 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 2, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "count" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n count - lag(count) OVER (ORDER BY \"time\") AS count\nFROM jsonrpc_request_duration\nWHERE\n $__timeFilter(\"time\")\nORDER BY 1", + "refId": "A", + "select": [ + [ + { + "params": [ + "sum" + ], + "type": "column" + } + ], + [ + { + "params": [ + "count" + ], + "type": "column" + } + ] + ], + "table": "jsonrpc_request_duration", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "jsonrpc_request_count", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "C" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "hide": true, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n count - lag(count) OVER (ORDER BY \"time\") AS count\nFROM jsonrpc_request_duration\nWHERE\n $__timeFilter(\"time\")\nORDER BY 1", + "refId": "A", + "select": [ + [ + { + "params": [ + "sum" + ], + "type": "column" + } + ], + [ + { + "params": [ + "count" + ], + "type": "column" + } + ] + ], + "table": "jsonrpc_request_duration", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + }, + { + "datasource": { + "type": "postgres", + "uid": "P51543FE1D179F612" + }, + "format": "time_series", + "group": [], + "hide": true, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n \"time\" AS \"time\",\n sum - lag(sum) OVER (ORDER BY \"time\") AS sum\nFROM jsonrpc_request_duration\nWHERE\n $__timeFilter(\"time\")\nORDER BY 1", + "refId": "B", + "select": [ + [ + { + "params": [ + "usage_percent" + ], + "type": "column" + } + ] + ], + "table": "docker_container_cpu", + "timeColumn": "\"time\"", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + }, + { + "datasource": { + "name": "Expression", + "type": "__expr__", + "uid": "__expr__" + }, + "expression": "$B/$A", + "hide": false, + "refId": "C", + "type": "math" + } + ], + "title": "jsonrpc_request_duration", + "transformations": [], + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-12h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Node metrics", + "uid": "g3kco8d4k", + "version": 2, + "weekStart": "" + } \ No newline at end of file diff --git a/test/config/grafana/dashboards.yml b/test/config/grafana/dashboards.yml new file mode 100644 index 0000000000..78ecb862f6 --- /dev/null +++ b/test/config/grafana/dashboards.yml @@ -0,0 +1,13 @@ +apiVersion: 1 + +providers: + - name: 'Dockers' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + allowUiUpdates: false + options: + path: /etc/grafana/provisioning/dashboards + foldersFromFilesStructure: true diff --git a/test/config/grafana/datasources.yml b/test/config/grafana/datasources.yml new file mode 100644 index 0000000000..29b3432feb --- /dev/null +++ b/test/config/grafana/datasources.yml @@ -0,0 +1,18 @@ +apiVersion: 1 + +datasources: + - name: Grafana-DB + isDefault: true + type: postgres + url: grafana-db:5432 + database: grafana + user: user + secureJsonData: + password: 'password' + jsonData: + sslmode: 'disable' # disable/require/verify-ca/verify-full + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ + postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 + timescaledb: false diff --git a/test/config/prover.config.test.json b/test/config/prover.config.test.json deleted file mode 100644 index 5b464f2137..0000000000 --- a/test/config/prover.config.test.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "runProverServer": false, - "runProverServerMock": true, - "runProverClient": false, - - "runExecutorServer": true, - "runExecutorClient": false, - - "runStateDBServer": true, - "runStateDBTest": false, - - "runFile": false, - "runFileFast": false, - - "runKeccakScriptGenerator": false, - "runKeccakTest": false, - "runStorageSMTest": false, - "runBinarySMTest": false, - "runMemAlignSMTest": false, - "runStarkTest": false, - - "executeInParallel" : false, - "useMainExecGenerated" : false, - - "proverServerPort": 50051, - "proverServerMockPort": 50052, - "proverClientPort": 50051, - "proverServerMockTimeout": 100000, - - "executorServerPort": 50071, - "executorClientPort": 50071, - "executorClientHost": "127.0.0.1", - - "stateDBServerPort": 50061, - "stateDBURL": "local", - - "inputFile": "input_executor.json", - "outputPath": "output", - "romFile": "rom.json", - "pilFile": "zkevm.pil.json", - "cmPolsFile": "commit.bin", - "constPolsFile": "constants.bin", - "constantsTreeFile": "constantstree.bin", - "scriptFile": "starkgen_bmscript.json", - "starkFile_disabled": "stark.json", - "verifierFile": "verifier.dat", - "witnessFile_disabled": "witness.wtns", - "starkVerifierFile": "starkverifier_0001.zkey", - "publicFile": "public.json", - "proofFile": "proof.json", - "keccakScriptFile": "keccak_script.json", - "keccakPolsFile_DISABLED": "keccak_pols.json", - "keccakConnectionsFile": "keccak_connections.json", - "storageRomFile": "storage_sm_rom.json", - "storagePilFile": "storage.pil.json", - "storagePolsFile": "storage.commit.bin", - "memoryPilFile": "mem.pil.json", - "memoryPolsFile": "mem.commit.bin", - "binaryPilFile": "binary.pil.json", - "binaryPolsFile": "binary.commit.bin", - "binaryConstPolsFile": "binary.constants.bin", - "starkInfoFile": "zkevm.starkinfo.json", - - "databaseURL": "postgresql://prover_user:prover_pass@zkevm-state-db:5432/prover_db", - "dbTableName": "state.merkletree", - "dbAsyncWrite": false, - "cleanerPollingPeriod": 600, - "requestsPersistence": 3600 -} diff --git a/test/config/telegraf.conf b/test/config/telegraf.conf new file mode 100644 index 0000000000..5b620f5697 --- /dev/null +++ b/test/config/telegraf.conf @@ -0,0 +1,15 @@ +[[inputs.docker]] + endpoint = "unix:///var/run/docker.sock" + gather_services = false + container_names = [] + source_tag = false + perdevice = true + total = true + tag_env = [] + +[[inputs.prometheus]] + ## An array of urls to scrape metrics from. + urls = ["http://zkevm-json-rpc:9091/metrics"] + +[[outputs.postgresql]] + connection = "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST/$POSTGRES_DB" diff --git a/test/config/test.genesis.config.json b/test/config/test.genesis.config.json new file mode 100644 index 0000000000..dc4a1e8bcb --- /dev/null +++ b/test/config/test.genesis.config.json @@ -0,0 +1,102 @@ +{ + "l1Config" : { + "chainId": 1337, + "polygonZkEVMAddress": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "maticTokenAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "polygonZkEVMGlobalExitRootAddress": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6" + }, + "root": "0xd88680f1b151dd67518f9aca85161424c0cac61df2f5424a3ddc04ea25adecc7", + "genesisBlockNumber": 65, + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0x4b2700570f8426A24EA85e0324611E527BdD55B8", + "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100e65780638da5cb5b146100fb578063e11ae6cb14610126578063f2fde38b1461013957600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610927565b610159565b005b6100886100983660046109c7565b6101cb565b3480156100a957600080fd5b506100bd6100b8366004610a1e565b61020d565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b50610088610220565b34801561010757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100bd565b610088610134366004610a40565b610234565b34801561014557600080fd5b50610088610154366004610a90565b61029b565b610161610357565b600061016e8585856103d8565b905061017a8183610537565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101d3610357565b6101de83838361057b565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b600061021983836105a9565b9392505050565b610228610357565b61023260006105b6565b565b61023c610357565b60006102498484846103d8565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b6102a3610357565b73ffffffffffffffffffffffffffffffffffffffff811661034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610354816105b6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610342565b600083471015610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610342565b81516000036104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610342565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610219576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610342565b6060610219838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061062b565b60606105a1848484604051806060016040528060298152602001610b3d6029913961062b565b949350505050565b6000610219838330610744565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610342565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516106e69190610acf565b60006040518083038185875af1925050503d8060008114610723576040519150601f19603f3d011682016040523d82523d6000602084013e610728565b606091505b50915091506107398783838761076e565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156108045782516000036107fd5773ffffffffffffffffffffffffffffffffffffffff85163b6107fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610342565b50816105a1565b6105a183838151156108195781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103429190610aeb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261088d57600080fd5b813567ffffffffffffffff808211156108a8576108a861084d565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108ee576108ee61084d565b8160405283815286602085880101111561090757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561093d57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561096357600080fd5b61096f8883890161087c565b9350606087013591508082111561098557600080fd5b506109928782880161087c565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff811681146109c257600080fd5b919050565b6000806000606084860312156109dc57600080fd5b6109e58461099e565b9250602084013567ffffffffffffffff811115610a0157600080fd5b610a0d8682870161087c565b925050604084013590509250925092565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600080600060608486031215610a5557600080fd5b8335925060208401359150604084013567ffffffffffffffff811115610a7a57600080fd5b610a868682870161087c565b9150509250925092565b600060208284031215610aa257600080fd5b6102198261099e565b60005b83811015610ac6578181015183820152602001610aae565b50506000910152565b60008251610ae1818460208701610aab565b9190910192915050565b6020815260008251806020840152610b0a816040850160208701610aab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212203e70ce334e8ec9d8d03e87415afd36dce4e82633bd277b08937095a6bd66367764736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0xf065BaE7C019ff5627E09ed48D4EeA317D211956", + "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461012b57806399a88ec41461013e578063f2fde38b1461015e578063f3b7dead1461017e57600080fd5b8063204e1c7a14610080578063715018a6146100c95780637eff275e146100e05780638da5cb5b14610100575b600080fd5b34801561008c57600080fd5b506100a061009b366004610608565b61019e565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d557600080fd5b506100de610255565b005b3480156100ec57600080fd5b506100de6100fb36600461062c565b610269565b34801561010c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166100a0565b6100de610139366004610694565b6102f7565b34801561014a57600080fd5b506100de61015936600461062c565b61038c565b34801561016a57600080fd5b506100de610179366004610608565b6103e8565b34801561018a57600080fd5b506100a0610199366004610608565b6104a4565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610225576040519150601f19603f3d011682016040523d82523d6000602084013e61022a565b606091505b50915091508161023957600080fd5b8080602001905181019061024d9190610788565b949350505050565b61025d6104f0565b6102676000610571565b565b6102716104f0565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b600060405180830381600087803b1580156102db57600080fd5b505af11580156102ef573d6000803e3d6000fd5b505050505050565b6102ff6104f0565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061035590869086906004016107a5565b6000604051808303818588803b15801561036e57600080fd5b505af1158015610382573d6000803e3d6000fd5b5050505050505050565b6103946104f0565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102c1565b6103f06104f0565b73ffffffffffffffffffffffffffffffffffffffff8116610498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104a181610571565b50565b60008060008373ffffffffffffffffffffffffffffffffffffffff166040516101ea907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b60005473ffffffffffffffffffffffffffffffffffffffff163314610267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161048f565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811681146104a157600080fd5b60006020828403121561061a57600080fd5b8135610625816105e6565b9392505050565b6000806040838503121561063f57600080fd5b823561064a816105e6565b9150602083013561065a816105e6565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156106a957600080fd5b83356106b4816105e6565b925060208401356106c4816105e6565b9150604084013567ffffffffffffffff808211156106e157600080fd5b818601915086601f8301126106f557600080fd5b81358181111561070757610707610665565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561074d5761074d610665565b8160405282815289602084870101111561076657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561079a57600080fd5b8151610625816105e6565b73ffffffffffffffffffffffffffffffffffffffff8316815260006020604081840152835180604085015260005b818110156107ef578581018301518582016060015282016107d3565b5060006060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea2646970667358221220372a0e10eebea1b7fa43ae4c976994e6ed01d85eedc3637b83f01d3f06be442064736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0xf23919bb44BCa81aeAb4586BE71Ee3fd4E99B951", + "bytecode": "0x6080604052600436106200019f5760003560e01c8063647c576c11620000e7578063be5831c71162000089578063dbc169761162000060578063dbc169761462000639578063ee25560b1462000651578063fb570834146200068257600080fd5b8063be5831c714620005ae578063cd58657914620005ea578063d02103ca146200060157600080fd5b80639e34070f11620000be5780639e34070f146200050a578063aaa13cc2146200054f578063bab161bf146200057457600080fd5b8063647c576c146200048657806379e2cf9714620004ab57806381b1c17414620004c357600080fd5b80632d2c9d94116200015157806334ac9cf2116200012857806334ac9cf2146200034b5780633ae05047146200037a5780633e197043146200039257600080fd5b80632d2c9d9414620002765780632dfdf0b5146200029b578063318aee3d14620002c257600080fd5b806322e95f2c116200018657806322e95f2c14620001ef578063240ff378146200023a5780632cffd02e146200025157600080fd5b806315064c9614620001a45780632072f6c514620001d5575b600080fd5b348015620001b157600080fd5b50606854620001c09060ff1681565b60405190151581526020015b60405180910390f35b348015620001e257600080fd5b50620001ed620006a7565b005b348015620001fc57600080fd5b50620002146200020e366004620032db565b62000705565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001cc565b620001ed6200024b36600462003372565b620007a8565b3480156200025e57600080fd5b50620001ed6200027036600462003409565b620009d0565b3480156200028357600080fd5b50620001ed6200029536600462003409565b62000f74565b348015620002a857600080fd5b50620002b360535481565b604051908152602001620001cc565b348015620002cf57600080fd5b5062000319620002e1366004620034ef565b606b6020526000908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001cc565b3480156200035857600080fd5b50606c54620002149073ffffffffffffffffffffffffffffffffffffffff1681565b3480156200038757600080fd5b50620002b362001178565b3480156200039f57600080fd5b50620002b3620003b136600462003526565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200049357600080fd5b50620001ed620004a5366004620035b0565b6200125e565b348015620004b857600080fd5b50620001ed620014ad565b348015620004d057600080fd5b5062000214620004e236600462003600565b606a6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200051757600080fd5b50620001c06200052936600462003600565b600881901c600090815260696020526040902054600160ff9092169190911b9081161490565b3480156200055c57600080fd5b50620002146200056e3660046200361a565b620014e7565b3480156200058157600080fd5b506068546200059890610100900463ffffffff1681565b60405163ffffffff9091168152602001620001cc565b348015620005bb57600080fd5b506068546200059890790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001ed620005fb366004620036ce565b620016d3565b3480156200060e57600080fd5b50606854620002149065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156200064657600080fd5b50620001ed62001c37565b3480156200065e57600080fd5b50620002b36200067036600462003600565b60696020526000908152604090205481565b3480156200068f57600080fd5b50620001c0620006a136600462003770565b62001c93565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006f9576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362001d7c565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091206000908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007e6576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8681166101009092041614806200080c5750600263ffffffff861610155b1562000844576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163388883488886053546040516200089a9998979695949392919062003806565b60405180910390a1620009b8620009b26001606860019054906101000a900463ffffffff16338989348989604051620008d592919062003881565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b62001e10565b8215620009c957620009c962001f27565b5050505050565b60685460ff161562000a0e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000a258b8b8b8b8b8b8b8b8b8b8b600062001ffc565b73ffffffffffffffffffffffffffffffffffffffff861662000b01576040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a7a9190620038e6565b60006040518083038185875af1925050503d806000811462000ab9576040519150601f19603f3d011682016040523d82523d6000602084013e62000abe565b606091505b505090508062000afa576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000efc565b60685463ffffffff61010090910481169088160362000b435762000b3d73ffffffffffffffffffffffffffffffffffffffff87168585620021ed565b62000efc565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b166024820152600090603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e6e576000808062000c1886880188620039fb565b92509250925060008584848460405162000c329062003292565b62000c409392919062003abd565b8190604051809103906000f590508015801562000c61573d6000803e3d6000fd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f1990604401600060405180830381600087803b15801562000cd757600080fd5b505af115801562000cec573d6000803e3d6000fd5b5050505080606a600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e5c95949392919062003afa565b60405180910390a15050505062000ef9565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f1990604401600060405180830381600087803b15801562000edf57600080fd5b505af115801562000ef4573d6000803e3d6000fd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000fb2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000fc98b8b8b8b8b8b8b8b8b8b8b600162001ffc565b60008473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000ffc949392919062003b42565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200107f9190620038e6565b60006040518083038185875af1925050503d8060008114620010be576040519150601f19603f3d011682016040523d82523d6000602084013e620010c3565b606091505b5050905080620010ff576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b605354600090819081805b602081101562001255578083901c600116600103620011e65760338160208110620011b257620011b262003b8a565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062001213565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806200124c9062003be8565b91505062001183565b50919392505050565b600054610100900460ff16158080156200127f5750600054600160ff909116105b806200129b5750303b1580156200129b575060005460ff166001145b6200132d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200138c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905562001443620022c3565b8015620014a757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff16101562000703576200070362001f27565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200157d9062003292565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620015c8908d908d908d908d908d9060200162003c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001606929160200162003c64565b604051602081830303815290604052805190602001206040516020016200168f94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff161562001711576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200171b62002366565b60685463ffffffff888116610100909204161480620017415750600263ffffffff881610155b1562001779576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060608773ffffffffffffffffffffffffffffffffffffffff8816620017df57883414620017d5576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000925062001ad9565b341562001818576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089166000908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901562001908576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac90604401600060405180830381600087803b158015620018db57600080fd5b505af1158015620018f0573d6000803e3d6000fd5b50505050806020015194508060000151935062001ad7565b85156200191d576200191d898b8989620023db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200198b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b1919062003c97565b9050620019d773ffffffffffffffffffffffffffffffffffffffff8b1633308e620028f9565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa15801562001a45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a6b919062003c97565b905062001a79828262003cb1565b6068548c9850610100900463ffffffff169650935062001a998762002959565b62001aa48c62002a71565b62001aaf8d62002b7e565b60405160200162001ac39392919062003abd565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e868860535460405162001b1b98979695949392919062003cc7565b60405180910390a162001c0f620009b2600085878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b861562001c205762001c2062001f27565b5050505062001c2e60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c89576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200070362002c80565b600084815b602081101562001d6e57600163ffffffff8616821c8116900362001d0a5785816020811062001ccb5762001ccb62003b8a565b60200201358260405160200162001cec929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001d59565b8186826020811062001d205762001d2062003b8a565b602002013560405160200162001d40929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d658162003be8565b91505062001c98565b50821490505b949350505050565b60685460ff161562001dba576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b80600162001e216020600262003e79565b62001e2d919062003cb1565b6053541062001e68576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060536000815462001e7b9062003be8565b9182905550905060005b602081101562001f17578082901c60011660010362001ebd57826033826020811062001eb55762001eb562003b8a565b015550505050565b6033816020811062001ed35762001ed362003b8a565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001f0e9062003be8565b91505062001e85565b5062001f2262003e87565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001fad62001178565b6040518263ffffffff1660e01b815260040162001fcc91815260200190565b600060405180830381600087803b15801562001fe757600080fd5b505af1158015620014a7573d6000803e3d6000fd5b6200200d8b63ffffffff1662002d10565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b363200000000000000000000000000000000000000000000000000000000909252606481019190915260009165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303816000875af1158015620020b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020d6919062003c97565b90508060000362002112576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff88811661010090920416146200215c576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606854600090610100900463ffffffff166200217a5750896200217d565b508a5b620021a66200219d848c8c8c8c8c8c8c604051620008d592919062003881565b8f8f8462001c93565b620021dd576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001f229084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002d75565b600054610100900460ff166200235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6200070362002e88565b600260015403620023d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640162001324565b6002600155565b6000620023ec600482848662003eb6565b620023f79162003ee2565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620026765760008080808080806200245a896004818d62003eb6565b81019062002469919062003f2b565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614620024dd576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146200252d576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002567576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620026229190620038e6565b6000604051808303816000865af19150503d806000811462002661576040519150601f19603f3d011682016040523d82523d6000602084013e62002666565b606091505b50505050505050505050620009c9565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c0000000000000000000000000000000000000000000000000000000014620026f2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080808080806200270a8a6004818e62003eb6565b81019062002719919062003f86565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16146200278f576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87163014620027df576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f1691620028a39190620038e6565b6000604051808303816000865af19150503d8060008114620028e2576040519150601f19603f3d011682016040523d82523d6000602084013e620028e7565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014a79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002240565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde03000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff861691620029dd9190620038e6565b600060405180830381855afa9150503d806000811462002a1a576040519150601f19603f3d011682016040523d82523d6000602084013e62002a1f565b606091505b50915091508162002a66576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d74565b62001d748162002f21565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b41000000000000000000000000000000000000000000000000000000001790529051606091600091829173ffffffffffffffffffffffffffffffffffffffff86169162002af59190620038e6565b600060405180830381855afa9150503d806000811462002b32576040519150601f19603f3d011682016040523d82523d6000602084013e62002b37565b606091505b50915091508162002a66576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d74565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290516000918291829173ffffffffffffffffffffffffffffffffffffffff86169162002c019190620038e6565b600060405180830381855afa9150503d806000811462002c3e576040519150601f19603f3d011682016040523d82523d6000602084013e62002c43565b606091505b509150915081801562002c57575080516020145b62002c6457601262001d74565b8080602001905181019062001d74919062004012565b60018055565b60685460ff1662002cbd576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b600881901c60008181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009c9576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031119092919063ffffffff16565b80519091501562001f22578080602001905181019062002dfa919062004032565b62001f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162001324565b600054610100900460ff1662002c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162001324565b6060604082511062002f435781806020019051810190620007a2919062004052565b8151602003620030d35760005b60208110801562002f9b575082818151811062002f715762002f7162003b8a565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002fb6578062002fad8162003be8565b91505062002f50565b8060000362002ffa57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b60008167ffffffffffffffff81111562003018576200301862003891565b6040519080825280601f01601f19166020018201604052801562003043576020820181803683370190505b50905060005b82811015620030cb5784818151811062003067576200306762003b8a565b602001015160f81c60f81b82828151811062003087576200308762003b8a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620030c28162003be8565b91505062003049565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d748484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051620031489190620038e6565b60006040518083038185875af1925050503d806000811462003187576040519150601f19603f3d011682016040523d82523d6000602084013e6200318c565b606091505b50915091506200319f87838387620031aa565b979650505050505050565b60608315620032455782516000036200323d5773ffffffffffffffffffffffffffffffffffffffff85163b6200323d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162001324565b508162001d74565b62001d7483838151156200325c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620013249190620040d2565b611b6680620040e883390190565b803563ffffffff811681146200310c57600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620032d857600080fd5b50565b60008060408385031215620032ef57600080fd5b620032fa83620032a0565b915060208301356200330c81620032b5565b809150509250929050565b8015158114620032d857600080fd5b60008083601f8401126200333957600080fd5b50813567ffffffffffffffff8111156200335257600080fd5b6020830191508360208285010111156200336b57600080fd5b9250929050565b6000806000806000608086880312156200338b57600080fd5b6200339686620032a0565b94506020860135620033a881620032b5565b93506040860135620033ba8162003317565b9250606086013567ffffffffffffffff811115620033d757600080fd5b620033e58882890162003326565b969995985093965092949392505050565b806104008101831015620007a257600080fd5b60008060008060008060008060008060006105208c8e0312156200342c57600080fd5b620034388d8d620033f6565b9a50620034496104008d01620032a0565b99506104208c013598506104408c013597506200346a6104608d01620032a0565b96506104808c01356200347d81620032b5565b95506200348e6104a08d01620032a0565b94506104c08c0135620034a181620032b5565b93506104e08c013592506105008c013567ffffffffffffffff811115620034c757600080fd5b620034d58e828f0162003326565b915080935050809150509295989b509295989b9093969950565b6000602082840312156200350257600080fd5b81356200350f81620032b5565b9392505050565b60ff81168114620032d857600080fd5b600080600080600080600060e0888a0312156200354257600080fd5b87356200354f8162003516565b96506200355f60208901620032a0565b955060408801356200357181620032b5565b94506200358160608901620032a0565b935060808801356200359381620032b5565b9699959850939692959460a0840135945060c09093013592915050565b600080600060608486031215620035c657600080fd5b620035d184620032a0565b92506020840135620035e381620032b5565b91506040840135620035f581620032b5565b809150509250925092565b6000602082840312156200361357600080fd5b5035919050565b600080600080600080600060a0888a0312156200363657600080fd5b6200364188620032a0565b965060208801356200365381620032b5565b9550604088013567ffffffffffffffff808211156200367157600080fd5b6200367f8b838c0162003326565b909750955060608a01359150808211156200369957600080fd5b50620036a88a828b0162003326565b9094509250506080880135620036be8162003516565b8091505092959891949750929550565b600080600080600080600060c0888a031215620036ea57600080fd5b620036f588620032a0565b965060208801356200370781620032b5565b95506040880135945060608801356200372081620032b5565b93506080880135620037328162003317565b925060a088013567ffffffffffffffff8111156200374f57600080fd5b6200375d8a828b0162003326565b989b979a50959850939692959293505050565b60008060008061046085870312156200378857600080fd5b843593506200379b8660208701620033f6565b9250620037ac6104208601620032a0565b939692955092936104400135925050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620038678285018789620037bd565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811015620038dd578181015183820152602001620038c3565b50506000910152565b60008251620038fa818460208701620038c0565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200394e576200394e62003891565b604052919050565b600067ffffffffffffffff82111562003973576200397362003891565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620039b157600080fd5b8135620039c8620039c28262003956565b62003904565b818152846020838601011115620039de57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121562003a1157600080fd5b833567ffffffffffffffff8082111562003a2a57600080fd5b62003a38878388016200399f565b9450602086013591508082111562003a4f57600080fd5b5062003a5e868287016200399f565b9250506040840135620035f58162003516565b6000815180845262003a8b816020860160208601620038c0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60608152600062003ad2606083018662003a71565b828103602084015262003ae6818662003a71565b91505060ff83166040830152949350505050565b63ffffffff86168152600073ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200319f608083018486620037bd565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff8416602082015260606040820152600062003b80606083018486620037bd565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003c1c5762003c1c62003bb9565b5060010190565b60608152600062003c39606083018789620037bd565b828103602084015262003c4e818688620037bd565b91505060ff831660408301529695505050505050565b6000835162003c78818460208801620038c0565b83519083019062003c8e818360208801620038c0565b01949350505050565b60006020828403121562003caa57600080fd5b5051919050565b81810381811115620007a257620007a262003bb9565b600061010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003d278285018762003a71565b925080851660e085015250509998505050505050505050565b600181815b8085111562003d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d835762003d8362003bb9565b8085161562003d9157918102915b93841c939080029062003d45565b509250929050565b60008262003db857506001620007a2565b8162003dc757506000620007a2565b816001811462003de0576002811462003deb5762003e0b565b6001915050620007a2565b60ff84111562003dff5762003dff62003bb9565b50506001821b620007a2565b5060208310610133831016604e8410600b841016171562003e30575081810a620007a2565b62003e3c838362003d40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003e715762003e7162003bb9565b029392505050565b60006200350f838362003da7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000808585111562003ec757600080fd5b8386111562003ed557600080fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003f235780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a03121562003f4757600080fd5b873562003f5481620032b5565b9650602088013562003f6681620032b5565b955060408801359450606088013593506080880135620035938162003516565b600080600080600080600080610100898b03121562003fa457600080fd5b883562003fb181620032b5565b9750602089013562003fc381620032b5565b96506040890135955060608901359450608089013562003fe38162003317565b935060a089013562003ff58162003516565b979a969950949793969295929450505060c08201359160e0013590565b6000602082840312156200402557600080fd5b81516200350f8162003516565b6000602082840312156200404557600080fd5b81516200350f8162003317565b6000602082840312156200406557600080fd5b815167ffffffffffffffff8111156200407d57600080fd5b8201601f810184136200408f57600080fd5b8051620040a0620039c28262003956565b818152856020838501011115620040b657600080fd5b620040c9826020830160208601620038c0565b95945050505050565b6020815260006200350f602083018462003a7156fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220d9b3ca7b13ec80ac58634ddf0ecebe71e209a71f532614949b9e720413f50c8364736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "200000000000000000000000000", + "nonce": "1", + "address": "0xff0EE8ea08cEf5cb4322777F5CC3E8A584B8A4A0", + "bytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461088b565b610135565b61006b6100a33660046108a6565b61017f565b3480156100b457600080fd5b506100bd6101f3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461088b565b610231565b34801561011257600080fd5b506100bd61025e565b6101236102d4565b61013361012e6103ab565b6103b5565b565b61013d6103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481604051806020016040528060008152506000610419565b50565b61017461011b565b6101876103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101eb576101e68383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610419915050565b505050565b6101e661011b565b60006101fd6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103ab565b905090565b61022e61011b565b90565b6102396103d9565b73ffffffffffffffffffffffffffffffffffffffff1633036101775761017481610444565b60006102686103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610226576102216103d9565b60606102b183836040518060600160405280602781526020016109bb602791396104a5565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6102dc6103d9565b73ffffffffffffffffffffffffffffffffffffffff163303610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b600061022161052a565b3660008037600080366000845af43d6000803e8080156103d4573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b61042283610552565b60008251118061042f5750805b156101e65761043e838361028c565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61046d6103d9565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a16101748161059f565b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516104cf919061094d565b600060405180830381855af49150503d806000811461050a576040519150601f19603f3d011682016040523d82523d6000602084013e61050f565b606091505b5091509150610520868383876106ab565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103fd565b61055b81610753565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff8116610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103a2565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b6060831561074157825160000361073a5773ffffffffffffffffffffffffffffffffffffffff85163b61073a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a2565b508161074b565b61074b838361081e565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff81163b6107f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016103a2565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610665565b81511561082e5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a29190610969565b803573ffffffffffffffffffffffffffffffffffffffff8116811461088657600080fd5b919050565b60006020828403121561089d57600080fd5b6102b182610862565b6000806000604084860312156108bb57600080fd5b6108c484610862565b9250602084013567ffffffffffffffff808211156108e157600080fd5b818601915086601f8301126108f557600080fd5b81358181111561090457600080fd5b87602082850101111561091657600080fd5b6020830194508093505050509250925092565b60005b8381101561094457818101518382015260200161092c565b50506000910152565b6000825161095f818460208701610929565b9190910192915050565b6020815260008251806020840152610988816040850160208701610929565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220a1af0d6cb4f1e31496a4c5c1448913bce4bd6ad3a39e47c6f7190c114d6f9bf464736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000068": "0x00000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa0000000100", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000f065bae7c019ff5627e09ed48d4eea317d211956", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000f23919bb44bca81aeab4586be71ee3fd4e99b951" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610162565b60006020819052908152604090205481565b6100a061009b366004610162565b6100ee565b005b6100c97f000000000000000000000000ff0ee8ea08cef5cb4322777f5cc3e8a584b8a4a081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff0ee8ea08cef5cb4322777f5cc3e8a584b8a4a0161461015d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b60006020828403121561017457600080fd5b503591905056fea2646970667358221220a187fc278346c1b61c449ea3641002b6eac2bda3351a122a12c35099f933696864736f6c63430008110033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106ca565b610118565b61005b6100933660046106e5565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106ca565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103f1565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107e460279139610445565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb610519565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b83610541565b6040516001600160a01b038416907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a26000825111806103dc5750805b156101c3576103eb8383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61041a61035f565b604080516001600160a01b03928316815291841660208301520160405180910390a1610154816105e9565b6060833b6104a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b0316856040516104bf9190610794565b600060405180830381855af49150503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b509150915061050f828286610675565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b803b6105a55760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b03811661064e5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036105c8565b60608315610684575081610285565b8251156106945782518084602001fd5b8160405162461bcd60e51b815260040161032891906107b0565b80356001600160a01b03811681146106c557600080fd5b919050565b6000602082840312156106dc57600080fd5b610285826106ae565b6000806000604084860312156106fa57600080fd5b610703846106ae565b9250602084013567ffffffffffffffff8082111561072057600080fd5b818601915086601f83011261073457600080fd5b81358181111561074357600080fd5b87602082850101111561075557600080fd5b6020830194508093505050509250925092565b60005b8381101561078357818101518382015260200161076b565b838111156103eb5750506000910152565b600082516107a6818460208701610768565b9190910192915050565b60208152600082518060208401526107cf816040850160208701610768565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212204675187caf3a43285d9a2c1844a981e977bd52a85ff073e7fc649f73847d70a464736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000f065bae7c019ff5627e09ed48d4eea317d211956", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c9" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "bytecode": "0x6080604052600436106101c65760003560e01c806364d62353116100f7578063b1c5f42711610095578063d547741f11610064578063d547741f14610661578063e38335e514610681578063f23a6e6114610694578063f27a0c92146106d957600080fd5b8063b1c5f427146105af578063bc197c81146105cf578063c4d252f514610614578063d45c44351461063457600080fd5b80638f61f4f5116100d15780638f61f4f5146104e157806391d1485414610515578063a217fddf14610566578063b08e51c01461057b57600080fd5b806364d62353146104815780638065657f146104a15780638f2a0bb0146104c157600080fd5b8063248a9ca31161016457806331d507501161013e57806331d50750146103c857806336568abe146103e85780633a6aae7214610408578063584b153e1461046157600080fd5b8063248a9ca3146103475780632ab0f529146103775780632f2ff15d146103a857600080fd5b80630d3cf6fc116101a05780630d3cf6fc1461026b578063134008d31461029f57806313bc9f20146102b2578063150b7a02146102d257600080fd5b806301d5062a146101d257806301ffc9a7146101f457806307bd02651461022957600080fd5b366101cd57005b600080fd5b3480156101de57600080fd5b506101f26101ed366004611c52565b6106ee565b005b34801561020057600080fd5b5061021461020f366004611cc7565b610783565b60405190151581526020015b60405180910390f35b34801561023557600080fd5b5061025d7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610220565b34801561027757600080fd5b5061025d7f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101f26102ad366004611d09565b6107df565b3480156102be57600080fd5b506102146102cd366004611d75565b6108d7565b3480156102de57600080fd5b506103166102ed366004611e9a565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610220565b34801561035357600080fd5b5061025d610362366004611d75565b60009081526020819052604090206001015490565b34801561038357600080fd5b50610214610392366004611d75565b6000908152600160208190526040909120541490565b3480156103b457600080fd5b506101f26103c3366004611f02565b6108fd565b3480156103d457600080fd5b506102146103e3366004611d75565b610927565b3480156103f457600080fd5b506101f2610403366004611f02565b610940565b34801561041457600080fd5b5061043c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610220565b34801561046d57600080fd5b5061021461047c366004611d75565b6109f8565b34801561048d57600080fd5b506101f261049c366004611d75565b610a0e565b3480156104ad57600080fd5b5061025d6104bc366004611d09565b610ade565b3480156104cd57600080fd5b506101f26104dc366004611f73565b610b1d565b3480156104ed57600080fd5b5061025d7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b34801561052157600080fd5b50610214610530366004611f02565b60009182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561057257600080fd5b5061025d600081565b34801561058757600080fd5b5061025d7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b3480156105bb57600080fd5b5061025d6105ca366004612025565b610d4f565b3480156105db57600080fd5b506103166105ea36600461214e565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b34801561062057600080fd5b506101f261062f366004611d75565b610d94565b34801561064057600080fd5b5061025d61064f366004611d75565b60009081526001602052604090205490565b34801561066d57600080fd5b506101f261067c366004611f02565b610e8f565b6101f261068f366004612025565b610eb4565b3480156106a057600080fd5b506103166106af3660046121f8565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106e557600080fd5b5061025d611161565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161071881611244565b6000610728898989898989610ade565b90506107348184611251565b6000817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a604051610770969594939291906122a6565b60405180910390a3505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107d957506107d98261139e565b92915050565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661085c5761085c8133611435565b600061086c888888888888610ade565b905061087881856114ed565b6108848888888861162a565b6000817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a6040516108bc94939291906122f1565b60405180910390a36108cd8161172e565b5050505050505050565b6000818152600160205260408120546001811180156108f65750428111155b9392505050565b60008281526020819052604090206001015461091881611244565b61092283836117d7565b505050565b60008181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109f482826118c7565b5050565b6000818152600160208190526040822054610939565b333014610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109e1565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b6000868686868686604051602001610afb969594939291906122a6565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b4781611244565b888714610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b888514610c65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b6000610c778b8b8b8b8b8b8b8b610d4f565b9050610c838184611251565b60005b8a811015610d415780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610cc357610cc3612331565b9050602002016020810190610cd89190612360565b8d8d86818110610cea57610cea612331565b905060200201358c8c87818110610d0357610d03612331565b9050602002810190610d15919061237b565b8c8b604051610d29969594939291906122a6565b60405180910390a3610d3a8161240f565b9050610c86565b505050505050505050505050565b60008888888888888888604051602001610d709897969594939291906124f7565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610dbe81611244565b610dc7826109f8565b610e53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109e1565b6000828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b600082815260208190526040902060010154610eaa81611244565b61092283836118c7565b600080527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610f3157610f318133611435565b878614610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b87841461104f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109e1565b60006110618a8a8a8a8a8a8a8a610d4f565b905061106d81856114ed565b60005b8981101561114b5760008b8b8381811061108c5761108c612331565b90506020020160208101906110a19190612360565b905060008a8a848181106110b7576110b7612331565b9050602002013590503660008a8a868181106110d5576110d5612331565b90506020028101906110e7919061237b565b915091506110f78484848461162a565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588686868660405161112e94939291906122f1565b60405180910390a350505050806111449061240f565b9050611070565b506111558161172e565b50505050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff161580159061123257507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123291906125be565b1561123d5750600090565b5060025490565b61124e8133611435565b50565b61125a82610927565b156112e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109e1565b6112ef611161565b81101561137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109e1565b61138881426125e0565b6000928352600160205260409092209190915550565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107d957507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107d9565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f4576114738161197e565b61147e83602061199d565b60405160200161148f929190612617565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109e191600401612698565b6114f6826108d7565b611582576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b80158061159e5750600081815260016020819052604090912054145b6109f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109e1565b60008473ffffffffffffffffffffffffffffffffffffffff168484846040516116549291906126e9565b60006040518083038185875af1925050503d8060008114611691576040519150601f19603f3d011682016040523d82523d6000602084013e611696565b606091505b5050905080611727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109e1565b5050505050565b611737816108d7565b6117c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109e1565b600090815260016020819052604090912055565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556118693390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109f45760008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107d973ffffffffffffffffffffffffffffffffffffffff831660145b606060006119ac8360026126f9565b6119b79060026125e0565b67ffffffffffffffff8111156119cf576119cf611d8e565b6040519080825280601f01601f1916602001820160405280156119f9576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611a3057611a30612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a9357611a93612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506000611acf8460026126f9565b611ada9060016125e0565b90505b6001811115611b77577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611b1b57611b1b612331565b1a60f81b828281518110611b3157611b31612331565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c93611b7081612710565b9050611add565b5083156108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109e1565b803573ffffffffffffffffffffffffffffffffffffffff81168114611c0457600080fd5b919050565b60008083601f840112611c1b57600080fd5b50813567ffffffffffffffff811115611c3357600080fd5b602083019150836020828501011115611c4b57600080fd5b9250929050565b600080600080600080600060c0888a031215611c6d57600080fd5b611c7688611be0565b965060208801359550604088013567ffffffffffffffff811115611c9957600080fd5b611ca58a828b01611c09565b989b979a50986060810135976080820135975060a09091013595509350505050565b600060208284031215611cd957600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108f657600080fd5b60008060008060008060a08789031215611d2257600080fd5b611d2b87611be0565b955060208701359450604087013567ffffffffffffffff811115611d4e57600080fd5b611d5a89828a01611c09565b979a9699509760608101359660809091013595509350505050565b600060208284031215611d8757600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e0457611e04611d8e565b604052919050565b600082601f830112611e1d57600080fd5b813567ffffffffffffffff811115611e3757611e37611d8e565b611e6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611dbd565b818152846020838601011115611e7d57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611eb057600080fd5b611eb985611be0565b9350611ec760208601611be0565b925060408501359150606085013567ffffffffffffffff811115611eea57600080fd5b611ef687828801611e0c565b91505092959194509250565b60008060408385031215611f1557600080fd5b82359150611f2560208401611be0565b90509250929050565b60008083601f840112611f4057600080fd5b50813567ffffffffffffffff811115611f5857600080fd5b6020830191508360208260051b8501011115611c4b57600080fd5b600080600080600080600080600060c08a8c031215611f9157600080fd5b893567ffffffffffffffff80821115611fa957600080fd5b611fb58d838e01611f2e565b909b50995060208c0135915080821115611fce57600080fd5b611fda8d838e01611f2e565b909950975060408c0135915080821115611ff357600080fd5b506120008c828d01611f2e565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b60008060008060008060008060a0898b03121561204157600080fd5b883567ffffffffffffffff8082111561205957600080fd5b6120658c838d01611f2e565b909a50985060208b013591508082111561207e57600080fd5b61208a8c838d01611f2e565b909850965060408b01359150808211156120a357600080fd5b506120b08b828c01611f2e565b999c989b509699959896976060870135966080013595509350505050565b600082601f8301126120df57600080fd5b8135602067ffffffffffffffff8211156120fb576120fb611d8e565b8160051b61210a828201611dbd565b928352848101820192828101908785111561212457600080fd5b83870192505b848310156121435782358252918301919083019061212a565b979650505050505050565b600080600080600060a0868803121561216657600080fd5b61216f86611be0565b945061217d60208701611be0565b9350604086013567ffffffffffffffff8082111561219a57600080fd5b6121a689838a016120ce565b945060608801359150808211156121bc57600080fd5b6121c889838a016120ce565b935060808801359150808211156121de57600080fd5b506121eb88828901611e0c565b9150509295509295909350565b600080600080600060a0868803121561221057600080fd5b61221986611be0565b945061222760208701611be0565b93506040860135925060608601359150608086013567ffffffffffffffff81111561225157600080fd5b6121eb88828901611e0c565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a0604082015260006122dc60a08301868861225d565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015260606040820152600061232760608301848661225d565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561237257600080fd5b6108f682611be0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126123b057600080fd5b83018035915067ffffffffffffffff8211156123cb57600080fd5b602001915036819003821315611c4b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612440576124406123e0565b5060010190565b81835260006020808501808196508560051b810191508460005b878110156124ea57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126124a057600080fd5b8701858101903567ffffffffffffffff8111156124bc57600080fd5b8036038213156124cb57600080fd5b6124d686828461225d565b9a87019a9550505090840190600101612461565b5091979650505050505050565b60a0808252810188905260008960c08301825b8b8110156125455773ffffffffffffffffffffffffffffffffffffffff61253084611be0565b1682526020928301929091019060010161250a565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff89111561257e57600080fd5b8860051b9150818a602083013701828103602090810160408501526125a69082018789612447565b60608401959095525050608001529695505050505050565b6000602082840312156125d057600080fd5b815180151581146108f657600080fd5b808201808211156107d9576107d96123e0565b60005b8381101561260e5781810151838201526020016125f6565b50506000910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081526000835161264f8160178501602088016125f3565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000601791840191820152835161268c8160288401602088016125f3565b01602801949350505050565b60208152600082518060208401526126b78160408501602087016125f3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b8183823760009101908152919050565b80820281158282048414176107d9576107d96123e0565b60008161271f5761271f6123e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212206416c4e08f97752b4bb06159524dac058d3dccd8775e57ef1b01505751ebf7af64736f6c63430008110033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0xaedcc9e7897c0d335bdc5d92fe3a8b4f23727fe558cd1c19f332b28716a30559": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xf5e61edb9c9cc6bfbae4463e9a2b1dd6ac3b44ddef38f18016e56ba0363910d9": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x60b9d94c75b7b3f721925089391e4644cd890cb5e6466f9596dfbd2c54e0b280": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x4b63b79f1e338a49559dcd3193ac9eecc50d0f275d24e97cc8c319e5a31a8bd0": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x800d5dfe4bba53eedee06cd4546a27da8de00f12db83f56062976d4493fda899": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x20E7077d25fe79C5F6c2D3ae4905E96aA7C89c13" + }, + { + "accountName": "deployer", + "balance": "100000000000000000000000", + "nonce": "8", + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ] + } \ No newline at end of file diff --git a/test/config/test.node.config.toml b/test/config/test.node.config.toml new file mode 100644 index 0000000000..fef5137138 --- /dev/null +++ b/test/config/test.node.config.toml @@ -0,0 +1,155 @@ +IsTrustedSequencer = true + +[Log] +Environment = "development" # "production" or "development" +Level = "debug" +Outputs = ["stderr"] + +[StateDB] +User = "state_user" +Password = "state_password" +Name = "state_db" +Host = "zkevm-state-db" +Port = "5432" +EnableLog = false +MaxConns = 200 + +[Pool] +FreeClaimGasLimit = 1500000 +IntervalToRefreshBlockedAddresses = "5m" +MaxTxBytesSize=100132 +MaxTxDataBytesSize=100000 +DefaultMinGasPriceAllowed = 1000000000 +MinAllowedGasPriceInterval = "5m" +PollMinAllowedGasPriceInterval = "15s" + [Pool.DB] + User = "pool_user" + Password = "pool_password" + Name = "pool_db" + Host = "zkevm-pool-db" + Port = "5432" + EnableLog = false + MaxConns = 200 + +[Etherman] +URL = "http://zkevm-mock-l1-network:8545" +MultiGasProvider = false + [Etherscan] + ApiKey = "" + +[RPC] +Host = "0.0.0.0" +Port = 8123 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 5000 +SequencerNodeURI = "" +EnableL2SuggestedGasPricePolling = true + [RPC.WebSockets] + Enabled = true + Port = 8133 + +[Synchronizer] +SyncInterval = "1s" +SyncChunkSize = 100 +TrustedSequencerURL = "" # If it is empty or not specified, then the value is read from the smc. + +[Sequencer] +WaitPeriodPoolIsEmpty = "1s" +LastBatchVirtualizationTimeMaxWaitPeriod = "10s" +BlocksAmountForTxsToBeDeleted = 100 +FrequencyToCheckTxsForDelete = "12h" +MaxTxsPerBatch = 150 +MaxBatchBytesSize = 129848 +MaxCumulativeGasUsed = 30000000 +MaxKeccakHashes = 468 +MaxPoseidonHashes = 279620 +MaxPoseidonPaddings = 149796 +MaxMemAligns = 262144 +MaxArithmetics = 262144 +MaxBinaries = 262144 +MaxSteps = 8388608 +WeightBatchBytesSize = 1 +WeightCumulativeGasUsed = 1 +WeightKeccakHashes = 1 +WeightPoseidonHashes = 1 +WeightPoseidonPaddings = 1 +WeightMemAligns = 1 +WeightArithmetics = 1 +WeightBinaries = 1 +WeightSteps = 1 +TxLifetimeCheckTimeout = "10m" +MaxTxLifetime = "3h" + [Sequencer.Finalizer] + GERDeadlineTimeout = "2s" + ForcedBatchDeadlineTimeout = "5s" + SleepDuration = "100ms" + ResourcePercentageToCloseBatch = 10 + GERFinalityNumberOfBlocks = 0 + ClosingSignalsManagerWaitForCheckingL1Timeout = "10s" + ClosingSignalsManagerWaitForCheckingGER = "10s" + ClosingSignalsManagerWaitForCheckingForcedBatches = "10s" + ForcedBatchesFinalityNumberOfBlocks = 0 + TimestampResolution = "10s" + [Sequencer.DBManager] + PoolRetrievalInterval = "500ms" + L2ReorgRetrievalInterval = "5s" + [Sequencer.Worker] + ResourceCostMultiplier = 1000 + +[SequenceSender] +WaitPeriodSendSequence = "15s" +LastBatchVirtualizationTimeMaxWaitPeriod = "10s" +MaxTxSizeForL1 = 131072 +SenderAddress = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +PrivateKeys = [{Path = "/pk/sequencer.keystore", Password = "testonly"}] + +[Aggregator] +Host = "0.0.0.0" +Port = 50081 +ForkId = 2 +RetryTime = "5s" +VerifyProofInterval = "10s" +TxProfitabilityCheckerType = "acceptall" +TxProfitabilityMinReward = "1.1" +ProofStatePollingInterval = "5s" +SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +CleanupLockedProofsInterval = "2m" +GeneratingProofCleanupThreshold = "10m" + +[EthTxManager] +ForcedGas = 0 +PrivateKeys = [ + {Path = "/pk/sequencer.keystore", Password = "testonly"}, + {Path = "/pk/aggregator.keystore", Password = "testonly"} +] + +[L2GasPriceSuggester] +Type = "follower" +UpdatePeriod = "10s" +Factor = 0.5 +DefaultGasPriceWei = 1000000000 + +[MTClient] +URI = "zkevm-prover:50061" + +[Executor] +URI = "zkevm-prover:50071" + +[Metrics] +Host = "0.0.0.0" +Port = 9091 +Enabled = true +ProfilingHost = "0.0.0.0" +ProfilingPort = 6060 +ProfilingEnabled = true + +[EventLog] + [EventLog.DB] + User = "event_user" + Password = "event_password" + Name = "event_db" + Host = "zkevm-event-db" + Port = "5432" + EnableLog = false + MaxConns = 200 diff --git a/test/config/test.permissionless.prover.config.json b/test/config/test.permissionless.prover.config.json new file mode 100644 index 0000000000..75ea3e4427 --- /dev/null +++ b/test/config/test.permissionless.prover.config.json @@ -0,0 +1,85 @@ +{ + "runExecutorServer": true, + "runExecutorClient": false, + "runExecutorClientMultithread": false, + + "runStateDBServer": true, + "runStateDBTest": false, + + "runAggregatorServer": false, + "runAggregatorClient": false, + "runAggregatorClientMock": true, + "aggregatorClientMockTimeout": 15000000, + "proverName": "test-prover", + + "runFileGenBatchProof": false, + "runFileGenAggregatedProof": false, + "runFileGenFinalProof": false, + "runFileProcessBatch": false, + "runFileProcessBatchMultithread": false, + + "runKeccakScriptGenerator": false, + "runKeccakTest": false, + "runStorageSMTest": false, + "runBinarySMTest": false, + "runMemAlignSMTest": false, + "runSHA256Test": false, + "runBlakeTest": false, + + "executeInParallel": true, + "useMainExecGenerated": false, + "saveRequestToFile": false, + "saveInputToFile": false, + "saveDbReadsToFile": false, + "saveDbReadsToFileOnChange": false, + "saveOutputToFile": true, + "saveProofToFile": true, + "saveResponseToFile": false, + "loadDBToMemCache": true, + "opcodeTracer": false, + "logRemoteDbReads": false, + "logExecutorServerResponses": false, + + "proverServerPort": 50051, + "proverServerMockPort": 50052, + "proverServerMockTimeout": 10000000, + "proverClientPort": 50051, + "proverClientHost": "127.0.0.1", + + "executorServerPort": 50071, + "executorROMLineTraces": false, + "executorClientPort": 50071, + "executorClientHost": "127.0.0.1", + + "stateDBServerPort": 50061, + "stateDBURL": "local", + + "aggregatorServerPort": 50081, + "aggregatorClientPort": 50081, + "aggregatorClientHost": "zkevm-aggregator", + + "mapConstPolsFile": false, + "mapConstantsTreeFile": false, + + "inputFile": "input_executor_0.json", + "inputFile2": "input_executor_1.json", + + "keccakScriptFile": "config/scripts/keccak_script.json", + "storageRomFile": "config/scripts/storage_sm_rom.json", + + "outputPath": "output", + + "databaseURL": "postgresql://prover_user:prover_pass@zkevm-permissionless-db:5432/prover_db", + "dbNodesTableName": "state.nodes", + "dbProgramTableName": "state.program", + "dbMultiWrite": true, + "dbFlushInParallel": false, + "dbMTCacheSize": 1024, + "dbProgramCacheSize": 1024, + "cleanerPollingPeriod": 600, + "requestsPersistence": 3600, + "maxExecutorThreads": 20, + "maxProverThreads": 8, + "maxStateDBThreads": 8 +} + diff --git a/test/config/test.prover.config.json b/test/config/test.prover.config.json new file mode 100644 index 0000000000..bd1eb2a187 --- /dev/null +++ b/test/config/test.prover.config.json @@ -0,0 +1,86 @@ +{ + "runExecutorServer": true, + "runExecutorClient": false, + "runExecutorClientMultithread": false, + + "runStateDBServer": true, + "runStateDBTest": false, + + "runAggregatorServer": false, + "runAggregatorClient": false, + "runAggregatorClientMock": true, + "aggregatorClientMockTimeout": 1, + "proverName": "test-prover", + + "runFileGenBatchProof": false, + "runFileGenAggregatedProof": false, + "runFileGenFinalProof": false, + "runFileProcessBatch": false, + "runFileProcessBatchMultithread": false, + + "runKeccakScriptGenerator": false, + "runKeccakTest": false, + "runStorageSMTest": false, + "runBinarySMTest": false, + "runMemAlignSMTest": false, + "runSHA256Test": false, + "runBlakeTest": false, + + "executeInParallel": true, + "useMainExecGenerated": false, + "saveRequestToFile": false, + "saveInputToFile": false, + "saveDbReadsToFile": false, + "saveDbReadsToFileOnChange": false, + "saveOutputToFile": true, + "saveProofToFile": true, + "saveResponseToFile": false, + "loadDBToMemCache": true, + "opcodeTracer": false, + "logRemoteDbReads": false, + "logExecutorServerResponses": false, + + "proverServerPort": 50051, + "proverServerMockPort": 50052, + "proverServerMockTimeout": 10000000, + "proverClientPort": 50051, + "proverClientHost": "127.0.0.1", + + "executorServerPort": 50071, + "executorROMLineTraces": false, + "executorClientPort": 50071, + "executorClientHost": "127.0.0.1", + + "stateDBServerPort": 50061, + "stateDBURL": "local", + + "aggregatorServerPort": 50081, + "aggregatorClientPort": 50081, + "aggregatorClientHost": "zkevm-aggregator", + + "mapConstPolsFile": false, + "mapConstantsTreeFile": false, + + "inputFile": "input_executor_0.json", + "inputFile2": "input_executor_1.json", + + "keccakScriptFile": "config/scripts/keccak_script.json", + "storageRomFile": "config/scripts/storage_sm_rom.json", + + "outputPath": "output", + + "databaseURL": "postgresql://prover_user:prover_pass@zkevm-state-db:5432/prover_db", + "dbNodesTableName": "state.nodes", + "dbProgramTableName": "state.program", + "dbMultiWrite": true, + "dbFlushInParallel": false, + "dbMTCacheSize": 1024, + "dbProgramCacheSize": 1024, + "dbNumberOfPoolConnections": 30, + "cleanerPollingPeriod": 600, + "requestsPersistence": 3600, + "maxExecutorThreads": 20, + "maxProverThreads": 8, + "maxStateDBThreads": 8 +} + diff --git a/test/constants/environment_variables.go b/test/constants/environment_variables.go new file mode 100644 index 0000000000..d1bfb26419 --- /dev/null +++ b/test/constants/environment_variables.go @@ -0,0 +1,8 @@ +package constants + +const ( + //ENV_ZKPROVER_URI environment variable name for ZKPROVER URI + ENV_ZKPROVER_URI = "ZKPROVER_URI" + //ENV_MERKLETREE_URI environment variable name for MERKLETREE URI + ENV_MERKLETREE_URI = "MERKLETREE_URI" +) diff --git a/test/constants/smart_contracts.go b/test/constants/smart_contracts.go new file mode 100644 index 0000000000..7b338d15f7 --- /dev/null +++ b/test/constants/smart_contracts.go @@ -0,0 +1,7 @@ +package constants + +import "github.com/ethereum/go-ethereum/crypto" + +var ( + ForcedBatchSignatureHash = crypto.Keccak256Hash([]byte("ForceBatch(uint64,bytes32,address,bytes)")) +) diff --git a/test/contracts/auto/Called.sol b/test/contracts/auto/Called.sol new file mode 100644 index 0000000000..9c8ed6031d --- /dev/null +++ b/test/contracts/auto/Called.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract Called { + uint256 num; + address sender; + uint256 value; + + function setVars(uint256 _num) public payable { + num = _num; + sender = msg.sender; + value = msg.value; + } + + function setVarsViaCall(uint256 _num) public payable { + bool ok; + (ok, ) = address(this).call( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform call"); + } + + function getVars() public view returns (uint256, address, uint256) { + return (num, sender, value); + } + + function getVarsAndVariable(uint256 _num) public view returns (uint256, address, uint256, uint256) { + return (num, sender, value, _num); + } +} diff --git a/test/contracts/auto/Caller.sol b/test/contracts/auto/Caller.sol new file mode 100644 index 0000000000..7e9915efbb --- /dev/null +++ b/test/contracts/auto/Caller.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract Caller { + function call(address _contract, uint _num) public payable { + bool ok; + (ok, ) = _contract.call( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform call"); + } + + function delegateCall(address _contract, uint _num) public payable { + bool ok; + (ok, ) = _contract.delegatecall( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform delegate call"); + } + + function staticCall(address _contract) public payable { + bool ok; + bytes memory result; + (ok, result) = _contract.staticcall( + abi.encodeWithSignature("getVars()") + ); + require(ok, "failed to perform static call"); + + uint256 num; + address sender; + uint256 value; + + (num, sender, value) = abi.decode(result, (uint256, address, uint256)); + } + + function invalidStaticCallMoreParameters(address _contract) public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)", 1, 2) + ); + require(!ok, "static call was supposed to fail with more parameters"); + } + + function invalidStaticCallLessParameters(address _contract) public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)") + ); + require(!ok, "static call was supposed to fail with less parameters"); + } + + function invalidStaticCallWithInnerCall(address _contract) public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)") + ); + require(!ok, "static call was supposed to fail with less parameters"); + } + + function multiCall(address _contract, uint _num) public payable { + call(_contract, _num); + delegateCall(_contract, _num); + staticCall(_contract); + } + + function preEcrecover_0() public { + bytes32 messHash = 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3; + uint8 v = 28; + bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; + bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; + + ecrecover(messHash, v, r, s); + } +} diff --git a/test/contracts/auto/ChainCallLevel1.sol b/test/contracts/auto/ChainCallLevel1.sol new file mode 100644 index 0000000000..67896d6d1d --- /dev/null +++ b/test/contracts/auto/ChainCallLevel1.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract ChainCallLevel1 { + function exec(address level2Addr, address level3Addr, address level4Addr) public payable { + bool ok; + (ok, ) = level2Addr.call( + abi.encodeWithSignature("exec(address,address)", level3Addr, level4Addr) + ); + require(ok, "failed to perform call to level 2"); + + (ok, ) = level2Addr.delegatecall( + abi.encodeWithSignature("exec(address,address)", level3Addr, level4Addr) + ); + require(ok, "failed to perform delegate call to level 2"); + + bytes memory result; + (ok, result) = level2Addr.staticcall( + abi.encodeWithSignature("get(address,address)", level3Addr, level4Addr) + ); + require(ok, "failed to perform static call to level 2"); + + string memory t; + (t) = abi.decode(result, (string)); + } +} diff --git a/test/contracts/auto/ChainCallLevel2.sol b/test/contracts/auto/ChainCallLevel2.sol new file mode 100644 index 0000000000..a70fd79f02 --- /dev/null +++ b/test/contracts/auto/ChainCallLevel2.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract ChainCallLevel2 { + function exec(address level3Addr, address level4Addr) public payable { + bool ok; + (ok, ) = level3Addr.call(abi.encodeWithSignature("exec(address)", level4Addr)); + require(ok, "failed to perform call to level 3"); + + (ok, ) = level3Addr.delegatecall(abi.encodeWithSignature("exec(address)", level4Addr)); + require(ok, "failed to perform delegate call to level 3"); + } + + function get(address level3Addr, address level4Addr) public view returns (string memory t) { + bool ok; + bytes memory result; + (ok, result) = level3Addr.staticcall(abi.encodeWithSignature("get(address)", level4Addr)); + require(ok, "failed to perform static call to level 3"); + + t = abi.decode(result, (string)); + + (ok, result) = level4Addr.staticcall(abi.encodeWithSignature("get()")); + require(ok, "failed to perform static call to level 4 from level 2"); + + t = abi.decode(result, (string)); + } +} diff --git a/test/contracts/auto/ChainCallLevel3.sol b/test/contracts/auto/ChainCallLevel3.sol new file mode 100644 index 0000000000..5228c52056 --- /dev/null +++ b/test/contracts/auto/ChainCallLevel3.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract ChainCallLevel3 { + function exec(address level4Addr) public payable { + bool ok; + (ok, ) = level4Addr.call(abi.encodeWithSignature("exec()")); + require(ok, "failed to perform call to level 4"); + + (ok, ) = level4Addr.delegatecall(abi.encodeWithSignature("exec()")); + require(ok, "failed to perform delegate call to level 4"); + } + + function get(address level4Addr) public view returns (string memory t) { + bool ok; + bytes memory result; + + (ok, result) = level4Addr.staticcall(abi.encodeWithSignature("get()")); + require(ok, "failed to perform static call to level 4"); + + t = abi.decode(result, (string)); + } +} diff --git a/test/contracts/auto/ChainCallLevel4.sol b/test/contracts/auto/ChainCallLevel4.sol new file mode 100644 index 0000000000..035e10a6c1 --- /dev/null +++ b/test/contracts/auto/ChainCallLevel4.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract ChainCallLevel4 { + address sender; + uint256 value; + + function exec() public payable { + sender = msg.sender; + value = msg.value; + } + + function get() public pure returns (string memory t) { + return "ahoy"; + } +} diff --git a/test/contracts/auto/Creates.sol b/test/contracts/auto/Creates.sol new file mode 100644 index 0000000000..cdd7c517ba --- /dev/null +++ b/test/contracts/auto/Creates.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +contract Creates { + function opCreate(bytes memory bytecode, uint length) public returns(address) { + address addr; + assembly { + addr := create(0, 0xa0, length) + sstore(0x0, addr) + } + return addr; + } + + function opCreate2(bytes memory bytecode, uint length) public returns(address) { + address addr; + assembly { + addr := create2(0, 0xa0, length, 0x2) + sstore(0x0, addr) + } + return addr; + } + + function opCreate2Complex(bytes memory bytecode, uint length) public returns(address, uint256) { + uint256 number = add(1, 2); + + address addr; + assembly { + addr := create2(0, add(bytecode, 0x20), length, 0x2) + sstore(0x0, addr) + } + + number = add(2, 4); + + return (addr, number); + } + + function add(uint256 a, uint256 b) public pure returns(uint256) { + return a + b; + } + + function sendValue() public payable { + uint bal; + assembly{ + bal := add(bal,callvalue()) + sstore(0x1, bal) + } + } + + function opCreateValue(bytes memory bytecode, uint length) public payable returns(address) { + address addr; + assembly { + addr := create(500, 0xa0, length) + sstore(0x0, addr) + } + return addr; + } + + function opCreate2Value(bytes memory bytecode, uint length) public payable returns(address) { + address addr; + assembly { + addr := create2(300, 0xa0, length, 0x55555) + sstore(0x0, addr) + } + return addr; + } +} \ No newline at end of file diff --git a/test/contracts/auto/DelegatecallReceiver.sol b/test/contracts/auto/DelegatecallReceiver.sol deleted file mode 100644 index e16a969aa7..0000000000 --- a/test/contracts/auto/DelegatecallReceiver.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -contract DelegatecallReceiver { - // storage from the caller will be copied to the callee. - address public expectedSender; - - bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; - - function entrypoint() external view { - require(expectedSender == msg.sender, string(abi.encodePacked('expectedSender ', toHexString(uint160(expectedSender), 20), ' actual sender ', toHexString(uint160(msg.sender), 20)))); - } - - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _HEX_SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - -} diff --git a/test/contracts/auto/DelegatecallSender.sol b/test/contracts/auto/DelegatecallSender.sol deleted file mode 100644 index 86aa51b117..0000000000 --- a/test/contracts/auto/DelegatecallSender.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.0; - -contract DelegatecallSender { - // storage of the caller will be copied to the callee. - address public expectedSender; - - function call(address target) public { - expectedSender = msg.sender; - - (bool success, bytes memory result) = target.delegatecall(abi.encodeWithSignature("entrypoint()")); - - if (!success) { - // Next 5 lines from https://ethereum.stackexchange.com/a/83577 - if (result.length < 68) revert(); - assembly { - result := add(result, 0x04) - } - revert(abi.decode(result, (string))); - } - require(success, 'delegated call failed'); - } -} diff --git a/test/contracts/auto/EmitLog2.sol b/test/contracts/auto/EmitLog2.sol index c2eee1461a..9954226a81 100644 --- a/test/contracts/auto/EmitLog2.sol +++ b/test/contracts/auto/EmitLog2.sol @@ -8,6 +8,9 @@ contract EmitLog2 { event LogABCD(uint256 indexed a, uint256 indexed b, uint256 indexed c, uint256 d); function emitLogs() public { + assembly { + log0(0, 32) + } emit Log(); emit LogA(1); emit LogABCD(1, 2, 3, 4); diff --git a/test/contracts/auto/Storage.sol b/test/contracts/auto/Storage.sol index d292c7e525..26472fc0e6 100644 --- a/test/contracts/auto/Storage.sol +++ b/test/contracts/auto/Storage.sol @@ -25,4 +25,8 @@ contract Storage { function retrieve() public view returns (uint256){ return number; } + + function release() public{ + number = 0; + } } diff --git a/test/contracts/bin/Called/Called.go b/test/contracts/bin/Called/Called.go new file mode 100644 index 0000000000..119c6d6b32 --- /dev/null +++ b/test/contracts/bin/Called/Called.go @@ -0,0 +1,312 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package Called + +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 + _ = abi.ConvertType +) + +// CalledMetaData contains all meta data concerning the Called contract. +var CalledMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"getVars\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"getVarsAndVariable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"setVars\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"setVarsViaCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061027f806100206000396000f3fe60806040526004361061003f5760003560e01c8063175df23c146100445780636466414b146100a6578063813d8a37146100d1578063f4bdc7341461010a575b600080fd5b34801561005057600080fd5b5061007961005f3660046101f5565b60005460015460025491936001600160a01b039091169290565b604080519485526001600160a01b0390931660208501529183015260608201526080015b60405180910390f35b6100cf6100b43660046101f5565b600055600180546001600160a01b0319163317905534600255565b005b3480156100dd57600080fd5b50600054600154600254604080519384526001600160a01b0390921660208401529082015260600161009d565b6100cf6101183660046101f5565b60405160248101829052600090309060440160408051601f198184030181529181526020820180516001600160e01b0316636466414b60e01b1790525161015f919061020e565b6000604051808303816000865af19150503d806000811461019c576040519150601f19603f3d011682016040523d82523d6000602084013e6101a1565b606091505b505080915050806101f15760405162461bcd60e51b815260206004820152601660248201527519985a5b1959081d1bc81c195c999bdc9b4818d85b1b60521b604482015260640160405180910390fd5b5050565b60006020828403121561020757600080fd5b5035919050565b6000825160005b8181101561022f5760208186018101518583015201610215565b8181111561023e576000828501525b50919091019291505056fea26469706673582212209d0d58578c55d453a185e4abef4bae0e18e22fd1b4c4e3d2072d42cbf3ccd4d864736f6c634300080c0033", +} + +// CalledABI is the input ABI used to generate the binding from. +// Deprecated: Use CalledMetaData.ABI instead. +var CalledABI = CalledMetaData.ABI + +// CalledBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use CalledMetaData.Bin instead. +var CalledBin = CalledMetaData.Bin + +// DeployCalled deploys a new Ethereum contract, binding an instance of Called to it. +func DeployCalled(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Called, error) { + parsed, err := CalledMetaData.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(CalledBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Called{CalledCaller: CalledCaller{contract: contract}, CalledTransactor: CalledTransactor{contract: contract}, CalledFilterer: CalledFilterer{contract: contract}}, nil +} + +// Called is an auto generated Go binding around an Ethereum contract. +type Called struct { + CalledCaller // Read-only binding to the contract + CalledTransactor // Write-only binding to the contract + CalledFilterer // Log filterer for contract events +} + +// CalledCaller is an auto generated read-only Go binding around an Ethereum contract. +type CalledCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CalledTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CalledTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CalledFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CalledFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CalledSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CalledSession struct { + Contract *Called // 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 +} + +// CalledCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CalledCallerSession struct { + Contract *CalledCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CalledTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CalledTransactorSession struct { + Contract *CalledTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CalledRaw is an auto generated low-level Go binding around an Ethereum contract. +type CalledRaw struct { + Contract *Called // Generic contract binding to access the raw methods on +} + +// CalledCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CalledCallerRaw struct { + Contract *CalledCaller // Generic read-only contract binding to access the raw methods on +} + +// CalledTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CalledTransactorRaw struct { + Contract *CalledTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCalled creates a new instance of Called, bound to a specific deployed contract. +func NewCalled(address common.Address, backend bind.ContractBackend) (*Called, error) { + contract, err := bindCalled(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Called{CalledCaller: CalledCaller{contract: contract}, CalledTransactor: CalledTransactor{contract: contract}, CalledFilterer: CalledFilterer{contract: contract}}, nil +} + +// NewCalledCaller creates a new read-only instance of Called, bound to a specific deployed contract. +func NewCalledCaller(address common.Address, caller bind.ContractCaller) (*CalledCaller, error) { + contract, err := bindCalled(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CalledCaller{contract: contract}, nil +} + +// NewCalledTransactor creates a new write-only instance of Called, bound to a specific deployed contract. +func NewCalledTransactor(address common.Address, transactor bind.ContractTransactor) (*CalledTransactor, error) { + contract, err := bindCalled(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CalledTransactor{contract: contract}, nil +} + +// NewCalledFilterer creates a new log filterer instance of Called, bound to a specific deployed contract. +func NewCalledFilterer(address common.Address, filterer bind.ContractFilterer) (*CalledFilterer, error) { + contract, err := bindCalled(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CalledFilterer{contract: contract}, nil +} + +// bindCalled binds a generic wrapper to an already deployed contract. +func bindCalled(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CalledMetaData.GetAbi() + 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 (_Called *CalledRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Called.Contract.CalledCaller.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 (_Called *CalledRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Called.Contract.CalledTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Called *CalledRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Called.Contract.CalledTransactor.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 (_Called *CalledCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Called.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 (_Called *CalledTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Called.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Called *CalledTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Called.Contract.contract.Transact(opts, method, params...) +} + +// GetVars is a free data retrieval call binding the contract method 0x813d8a37. +// +// Solidity: function getVars() view returns(uint256, address, uint256) +func (_Called *CalledCaller) GetVars(opts *bind.CallOpts) (*big.Int, common.Address, *big.Int, error) { + var out []interface{} + err := _Called.contract.Call(opts, &out, "getVars") + + if err != nil { + return *new(*big.Int), *new(common.Address), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + out2 := *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + + return out0, out1, out2, err + +} + +// GetVars is a free data retrieval call binding the contract method 0x813d8a37. +// +// Solidity: function getVars() view returns(uint256, address, uint256) +func (_Called *CalledSession) GetVars() (*big.Int, common.Address, *big.Int, error) { + return _Called.Contract.GetVars(&_Called.CallOpts) +} + +// GetVars is a free data retrieval call binding the contract method 0x813d8a37. +// +// Solidity: function getVars() view returns(uint256, address, uint256) +func (_Called *CalledCallerSession) GetVars() (*big.Int, common.Address, *big.Int, error) { + return _Called.Contract.GetVars(&_Called.CallOpts) +} + +// GetVarsAndVariable is a free data retrieval call binding the contract method 0x175df23c. +// +// Solidity: function getVarsAndVariable(uint256 _num) view returns(uint256, address, uint256, uint256) +func (_Called *CalledCaller) GetVarsAndVariable(opts *bind.CallOpts, _num *big.Int) (*big.Int, common.Address, *big.Int, *big.Int, error) { + var out []interface{} + err := _Called.contract.Call(opts, &out, "getVarsAndVariable", _num) + + if err != nil { + return *new(*big.Int), *new(common.Address), *new(*big.Int), *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + out2 := *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + out3 := *abi.ConvertType(out[3], new(*big.Int)).(**big.Int) + + return out0, out1, out2, out3, err + +} + +// GetVarsAndVariable is a free data retrieval call binding the contract method 0x175df23c. +// +// Solidity: function getVarsAndVariable(uint256 _num) view returns(uint256, address, uint256, uint256) +func (_Called *CalledSession) GetVarsAndVariable(_num *big.Int) (*big.Int, common.Address, *big.Int, *big.Int, error) { + return _Called.Contract.GetVarsAndVariable(&_Called.CallOpts, _num) +} + +// GetVarsAndVariable is a free data retrieval call binding the contract method 0x175df23c. +// +// Solidity: function getVarsAndVariable(uint256 _num) view returns(uint256, address, uint256, uint256) +func (_Called *CalledCallerSession) GetVarsAndVariable(_num *big.Int) (*big.Int, common.Address, *big.Int, *big.Int, error) { + return _Called.Contract.GetVarsAndVariable(&_Called.CallOpts, _num) +} + +// SetVars is a paid mutator transaction binding the contract method 0x6466414b. +// +// Solidity: function setVars(uint256 _num) payable returns() +func (_Called *CalledTransactor) SetVars(opts *bind.TransactOpts, _num *big.Int) (*types.Transaction, error) { + return _Called.contract.Transact(opts, "setVars", _num) +} + +// SetVars is a paid mutator transaction binding the contract method 0x6466414b. +// +// Solidity: function setVars(uint256 _num) payable returns() +func (_Called *CalledSession) SetVars(_num *big.Int) (*types.Transaction, error) { + return _Called.Contract.SetVars(&_Called.TransactOpts, _num) +} + +// SetVars is a paid mutator transaction binding the contract method 0x6466414b. +// +// Solidity: function setVars(uint256 _num) payable returns() +func (_Called *CalledTransactorSession) SetVars(_num *big.Int) (*types.Transaction, error) { + return _Called.Contract.SetVars(&_Called.TransactOpts, _num) +} + +// SetVarsViaCall is a paid mutator transaction binding the contract method 0xf4bdc734. +// +// Solidity: function setVarsViaCall(uint256 _num) payable returns() +func (_Called *CalledTransactor) SetVarsViaCall(opts *bind.TransactOpts, _num *big.Int) (*types.Transaction, error) { + return _Called.contract.Transact(opts, "setVarsViaCall", _num) +} + +// SetVarsViaCall is a paid mutator transaction binding the contract method 0xf4bdc734. +// +// Solidity: function setVarsViaCall(uint256 _num) payable returns() +func (_Called *CalledSession) SetVarsViaCall(_num *big.Int) (*types.Transaction, error) { + return _Called.Contract.SetVarsViaCall(&_Called.TransactOpts, _num) +} + +// SetVarsViaCall is a paid mutator transaction binding the contract method 0xf4bdc734. +// +// Solidity: function setVarsViaCall(uint256 _num) payable returns() +func (_Called *CalledTransactorSession) SetVarsViaCall(_num *big.Int) (*types.Transaction, error) { + return _Called.Contract.SetVarsViaCall(&_Called.TransactOpts, _num) +} diff --git a/test/contracts/bin/Caller/Caller.go b/test/contracts/bin/Caller/Caller.go new file mode 100644 index 0000000000..ac61e03bb2 --- /dev/null +++ b/test/contracts/bin/Caller/Caller.go @@ -0,0 +1,371 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package Caller + +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 + _ = abi.ConvertType +) + +// CallerMetaData contains all meta data concerning the Caller contract. +var CallerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"call\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"delegateCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"}],\"name\":\"invalidStaticCallLessParameters\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"}],\"name\":\"invalidStaticCallMoreParameters\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"}],\"name\":\"invalidStaticCallWithInnerCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"multiCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"preEcrecover_0\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_contract\",\"type\":\"address\"}],\"name\":\"staticCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506107e2806100206000396000f3fe60806040526004361061007b5760003560e01c806387b1d6ad1161004e57806387b1d6ad146100c8578063b3e554d0146100db578063c6c211e9146100fb578063fff0972f1461010e57600080fd5b80630f6be00d14610080578063351f14c5146100955780633bd9ef28146100b557806369c2b58f14610095575b600080fd5b61009361008e3660046106e8565b610123565b005b3480156100a157600080fd5b506100936100b0366004610714565b610214565b6100936100c33660046106e8565b61030b565b6100936100d6366004610714565b6103ed565b3480156100e757600080fd5b506100936100f6366004610714565b6104e8565b6100936101093660046106e8565b6105f0565b34801561011a57600080fd5b5061009361060d565b6000826001600160a01b03168260405160240161014291815260200190565b60408051601f198184030181529181526020820180516001600160e01b0316636466414b60e01b179052516101779190610738565b600060405180830381855af49150503d80600081146101b2576040519150601f19603f3d011682016040523d82523d6000602084013e6101b7565b606091505b5050809150508061020f5760405162461bcd60e51b815260206004820152601f60248201527f6661696c656420746f20706572666f726d2064656c65676174652063616c6c0060448201526064015b60405180910390fd5b505050565b60408051600481526024810182526020810180516001600160e01b03166305d77c8f60e21b17905290516000916001600160a01b038416916102569190610738565b600060405180830381855afa9150503d8060008114610291576040519150601f19603f3d011682016040523d82523d6000602084013e610296565b606091505b509091505080156103075760405162461bcd60e51b815260206004820152603560248201527f7374617469632063616c6c2077617320737570706f73656420746f206661696c6044820152742077697468206c65737320706172616d657465727360581b6064820152608401610206565b5050565b6000826001600160a01b03168260405160240161032a91815260200190565b60408051601f198184030181529181526020820180516001600160e01b0316636466414b60e01b1790525161035f9190610738565b6000604051808303816000865af19150503d806000811461039c576040519150601f19603f3d011682016040523d82523d6000602084013e6103a1565b606091505b5050809150508061020f5760405162461bcd60e51b815260206004820152601660248201527519985a5b1959081d1bc81c195c999bdc9b4818d85b1b60521b6044820152606401610206565b60408051600481526024810182526020810180516001600160e01b031663813d8a3760e01b17905290516000916060916001600160a01b0385169161043191610738565b600060405180830381855afa9150503d806000811461046c576040519150601f19603f3d011682016040523d82523d6000602084013e610471565b606091505b509092509050816104c45760405162461bcd60e51b815260206004820152601d60248201527f6661696c656420746f20706572666f726d207374617469632063616c6c0000006044820152606401610206565b6000806000838060200190518101906104dd9190610773565b505050505050505050565b60405160016024820152600260448201526000906001600160a01b0383169060640160408051601f198184030181529181526020820180516001600160e01b03166305d77c8f60e21b1790525161053f9190610738565b600060405180830381855afa9150503d806000811461057a576040519150601f19603f3d011682016040523d82523d6000602084013e61057f565b606091505b509091505080156103075760405162461bcd60e51b815260206004820152603560248201527f7374617469632063616c6c2077617320737570706f73656420746f206661696c6044820152742077697468206d6f726520706172616d657465727360581b6064820152608401610206565b6105fa828261030b565b6106048282610123565b610307826103ed565b6040805160008152602081018083527f456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef390819052601c9282018390527f9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608606083018190527f4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada6080840181905291939290919060019060a0016020604051602081039080840390855afa1580156106c7573d6000803e3d6000fd5b50505050505050565b6001600160a01b03811681146106e557600080fd5b50565b600080604083850312156106fb57600080fd5b8235610706816106d0565b946020939093013593505050565b60006020828403121561072657600080fd5b8135610731816106d0565b9392505050565b6000825160005b81811015610759576020818601810151858301520161073f565b81811115610768576000828501525b509190910192915050565b60008060006060848603121561078857600080fd5b83519250602084015161079a816106d0565b8092505060408401519050925092509256fea2646970667358221220a82281d9696e9c0b1485742fdc267f1a20789436e6606892338b4fa4f6f1e43e64736f6c634300080c0033", +} + +// CallerABI is the input ABI used to generate the binding from. +// Deprecated: Use CallerMetaData.ABI instead. +var CallerABI = CallerMetaData.ABI + +// CallerBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use CallerMetaData.Bin instead. +var CallerBin = CallerMetaData.Bin + +// DeployCaller deploys a new Ethereum contract, binding an instance of Caller to it. +func DeployCaller(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Caller, error) { + parsed, err := CallerMetaData.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(CallerBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Caller{CallerCaller: CallerCaller{contract: contract}, CallerTransactor: CallerTransactor{contract: contract}, CallerFilterer: CallerFilterer{contract: contract}}, nil +} + +// Caller is an auto generated Go binding around an Ethereum contract. +type Caller struct { + CallerCaller // Read-only binding to the contract + CallerTransactor // Write-only binding to the contract + CallerFilterer // Log filterer for contract events +} + +// CallerCaller is an auto generated read-only Go binding around an Ethereum contract. +type CallerCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallerTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CallerTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallerFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CallerFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallerSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CallerSession struct { + Contract *Caller // 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 +} + +// CallerCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CallerCallerSession struct { + Contract *CallerCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CallerTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CallerTransactorSession struct { + Contract *CallerTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CallerRaw is an auto generated low-level Go binding around an Ethereum contract. +type CallerRaw struct { + Contract *Caller // Generic contract binding to access the raw methods on +} + +// CallerCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CallerCallerRaw struct { + Contract *CallerCaller // Generic read-only contract binding to access the raw methods on +} + +// CallerTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CallerTransactorRaw struct { + Contract *CallerTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCaller creates a new instance of Caller, bound to a specific deployed contract. +func NewCaller(address common.Address, backend bind.ContractBackend) (*Caller, error) { + contract, err := bindCaller(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Caller{CallerCaller: CallerCaller{contract: contract}, CallerTransactor: CallerTransactor{contract: contract}, CallerFilterer: CallerFilterer{contract: contract}}, nil +} + +// NewCallerCaller creates a new read-only instance of Caller, bound to a specific deployed contract. +func NewCallerCaller(address common.Address, caller bind.ContractCaller) (*CallerCaller, error) { + contract, err := bindCaller(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CallerCaller{contract: contract}, nil +} + +// NewCallerTransactor creates a new write-only instance of Caller, bound to a specific deployed contract. +func NewCallerTransactor(address common.Address, transactor bind.ContractTransactor) (*CallerTransactor, error) { + contract, err := bindCaller(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CallerTransactor{contract: contract}, nil +} + +// NewCallerFilterer creates a new log filterer instance of Caller, bound to a specific deployed contract. +func NewCallerFilterer(address common.Address, filterer bind.ContractFilterer) (*CallerFilterer, error) { + contract, err := bindCaller(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CallerFilterer{contract: contract}, nil +} + +// bindCaller binds a generic wrapper to an already deployed contract. +func bindCaller(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CallerMetaData.GetAbi() + 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 (_Caller *CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Caller.Contract.CallerCaller.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 (_Caller *CallerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Caller.Contract.CallerTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Caller *CallerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Caller.Contract.CallerTransactor.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 (_Caller *CallerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Caller.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 (_Caller *CallerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Caller.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Caller *CallerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Caller.Contract.contract.Transact(opts, method, params...) +} + +// Call is a paid mutator transaction binding the contract method 0x3bd9ef28. +// +// Solidity: function call(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactor) Call(opts *bind.TransactOpts, _contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "call", _contract, _num) +} + +// Call is a paid mutator transaction binding the contract method 0x3bd9ef28. +// +// Solidity: function call(address _contract, uint256 _num) payable returns() +func (_Caller *CallerSession) Call(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.Call(&_Caller.TransactOpts, _contract, _num) +} + +// Call is a paid mutator transaction binding the contract method 0x3bd9ef28. +// +// Solidity: function call(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactorSession) Call(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.Call(&_Caller.TransactOpts, _contract, _num) +} + +// DelegateCall is a paid mutator transaction binding the contract method 0x0f6be00d. +// +// Solidity: function delegateCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactor) DelegateCall(opts *bind.TransactOpts, _contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "delegateCall", _contract, _num) +} + +// DelegateCall is a paid mutator transaction binding the contract method 0x0f6be00d. +// +// Solidity: function delegateCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerSession) DelegateCall(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.DelegateCall(&_Caller.TransactOpts, _contract, _num) +} + +// DelegateCall is a paid mutator transaction binding the contract method 0x0f6be00d. +// +// Solidity: function delegateCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactorSession) DelegateCall(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.DelegateCall(&_Caller.TransactOpts, _contract, _num) +} + +// InvalidStaticCallLessParameters is a paid mutator transaction binding the contract method 0x69c2b58f. +// +// Solidity: function invalidStaticCallLessParameters(address _contract) returns() +func (_Caller *CallerTransactor) InvalidStaticCallLessParameters(opts *bind.TransactOpts, _contract common.Address) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "invalidStaticCallLessParameters", _contract) +} + +// InvalidStaticCallLessParameters is a paid mutator transaction binding the contract method 0x69c2b58f. +// +// Solidity: function invalidStaticCallLessParameters(address _contract) returns() +func (_Caller *CallerSession) InvalidStaticCallLessParameters(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallLessParameters(&_Caller.TransactOpts, _contract) +} + +// InvalidStaticCallLessParameters is a paid mutator transaction binding the contract method 0x69c2b58f. +// +// Solidity: function invalidStaticCallLessParameters(address _contract) returns() +func (_Caller *CallerTransactorSession) InvalidStaticCallLessParameters(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallLessParameters(&_Caller.TransactOpts, _contract) +} + +// InvalidStaticCallMoreParameters is a paid mutator transaction binding the contract method 0xb3e554d0. +// +// Solidity: function invalidStaticCallMoreParameters(address _contract) returns() +func (_Caller *CallerTransactor) InvalidStaticCallMoreParameters(opts *bind.TransactOpts, _contract common.Address) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "invalidStaticCallMoreParameters", _contract) +} + +// InvalidStaticCallMoreParameters is a paid mutator transaction binding the contract method 0xb3e554d0. +// +// Solidity: function invalidStaticCallMoreParameters(address _contract) returns() +func (_Caller *CallerSession) InvalidStaticCallMoreParameters(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallMoreParameters(&_Caller.TransactOpts, _contract) +} + +// InvalidStaticCallMoreParameters is a paid mutator transaction binding the contract method 0xb3e554d0. +// +// Solidity: function invalidStaticCallMoreParameters(address _contract) returns() +func (_Caller *CallerTransactorSession) InvalidStaticCallMoreParameters(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallMoreParameters(&_Caller.TransactOpts, _contract) +} + +// InvalidStaticCallWithInnerCall is a paid mutator transaction binding the contract method 0x351f14c5. +// +// Solidity: function invalidStaticCallWithInnerCall(address _contract) returns() +func (_Caller *CallerTransactor) InvalidStaticCallWithInnerCall(opts *bind.TransactOpts, _contract common.Address) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "invalidStaticCallWithInnerCall", _contract) +} + +// InvalidStaticCallWithInnerCall is a paid mutator transaction binding the contract method 0x351f14c5. +// +// Solidity: function invalidStaticCallWithInnerCall(address _contract) returns() +func (_Caller *CallerSession) InvalidStaticCallWithInnerCall(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallWithInnerCall(&_Caller.TransactOpts, _contract) +} + +// InvalidStaticCallWithInnerCall is a paid mutator transaction binding the contract method 0x351f14c5. +// +// Solidity: function invalidStaticCallWithInnerCall(address _contract) returns() +func (_Caller *CallerTransactorSession) InvalidStaticCallWithInnerCall(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.InvalidStaticCallWithInnerCall(&_Caller.TransactOpts, _contract) +} + +// MultiCall is a paid mutator transaction binding the contract method 0xc6c211e9. +// +// Solidity: function multiCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactor) MultiCall(opts *bind.TransactOpts, _contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "multiCall", _contract, _num) +} + +// MultiCall is a paid mutator transaction binding the contract method 0xc6c211e9. +// +// Solidity: function multiCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerSession) MultiCall(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.MultiCall(&_Caller.TransactOpts, _contract, _num) +} + +// MultiCall is a paid mutator transaction binding the contract method 0xc6c211e9. +// +// Solidity: function multiCall(address _contract, uint256 _num) payable returns() +func (_Caller *CallerTransactorSession) MultiCall(_contract common.Address, _num *big.Int) (*types.Transaction, error) { + return _Caller.Contract.MultiCall(&_Caller.TransactOpts, _contract, _num) +} + +// PreEcrecover0 is a paid mutator transaction binding the contract method 0xfff0972f. +// +// Solidity: function preEcrecover_0() returns() +func (_Caller *CallerTransactor) PreEcrecover0(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "preEcrecover_0") +} + +// PreEcrecover0 is a paid mutator transaction binding the contract method 0xfff0972f. +// +// Solidity: function preEcrecover_0() returns() +func (_Caller *CallerSession) PreEcrecover0() (*types.Transaction, error) { + return _Caller.Contract.PreEcrecover0(&_Caller.TransactOpts) +} + +// PreEcrecover0 is a paid mutator transaction binding the contract method 0xfff0972f. +// +// Solidity: function preEcrecover_0() returns() +func (_Caller *CallerTransactorSession) PreEcrecover0() (*types.Transaction, error) { + return _Caller.Contract.PreEcrecover0(&_Caller.TransactOpts) +} + +// StaticCall is a paid mutator transaction binding the contract method 0x87b1d6ad. +// +// Solidity: function staticCall(address _contract) payable returns() +func (_Caller *CallerTransactor) StaticCall(opts *bind.TransactOpts, _contract common.Address) (*types.Transaction, error) { + return _Caller.contract.Transact(opts, "staticCall", _contract) +} + +// StaticCall is a paid mutator transaction binding the contract method 0x87b1d6ad. +// +// Solidity: function staticCall(address _contract) payable returns() +func (_Caller *CallerSession) StaticCall(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.StaticCall(&_Caller.TransactOpts, _contract) +} + +// StaticCall is a paid mutator transaction binding the contract method 0x87b1d6ad. +// +// Solidity: function staticCall(address _contract) payable returns() +func (_Caller *CallerTransactorSession) StaticCall(_contract common.Address) (*types.Transaction, error) { + return _Caller.Contract.StaticCall(&_Caller.TransactOpts, _contract) +} diff --git a/test/contracts/bin/ChainCallLevel1/ChainCallLevel1.go b/test/contracts/bin/ChainCallLevel1/ChainCallLevel1.go new file mode 100644 index 0000000000..606bafc144 --- /dev/null +++ b/test/contracts/bin/ChainCallLevel1/ChainCallLevel1.go @@ -0,0 +1,224 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ChainCallLevel1 + +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 + _ = abi.ConvertType +) + +// ChainCallLevel1MetaData contains all meta data concerning the ChainCallLevel1 contract. +var ChainCallLevel1MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"level2Addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"level3Addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"level4Addr\",\"type\":\"address\"}],\"name\":\"exec\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506104f3806100206000396000f3fe60806040526004361061001e5760003560e01c8063c023dcf314610023575b600080fd5b61003661003136600461036b565b610038565b005b6040516001600160a01b03838116602483015282811660448301526000919085169060640160408051601f198184030181529181526020820180516001600160e01b031663ee2d011560e01b1790525161009291906103de565b6000604051808303816000865af19150503d80600081146100cf576040519150601f19603f3d011682016040523d82523d6000602084013e6100d4565b606091505b505080915050806101365760405162461bcd60e51b815260206004820152602160248201527f6661696c656420746f20706572666f726d2063616c6c20746f206c6576656c206044820152601960f91b60648201526084015b60405180910390fd5b6040516001600160a01b038481166024830152838116604483015285169060640160408051601f198184030181529181526020820180516001600160e01b031663ee2d011560e01b1790525161018c91906103de565b600060405180830381855af49150503d80600081146101c7576040519150601f19603f3d011682016040523d82523d6000602084013e6101cc565b606091505b505080915050806102325760405162461bcd60e51b815260206004820152602a60248201527f6661696c656420746f20706572666f726d2064656c65676174652063616c6c206044820152693a37903632bb32b6101960b11b606482015260840161012d565b6040516001600160a01b03848116602483015283811660448301526060919086169060640160408051601f198184030181529181526020820180516001600160e01b031663d81e842360e01b1790525161028c91906103de565b600060405180830381855afa9150503d80600081146102c7576040519150601f19603f3d011682016040523d82523d6000602084013e6102cc565b606091505b509092509050816103305760405162461bcd60e51b815260206004820152602860248201527f6661696c656420746f20706572666f726d207374617469632063616c6c20746f604482015267103632bb32b6101960c11b606482015260840161012d565b6060818060200190518101906103469190610410565b50505050505050565b80356001600160a01b038116811461036657600080fd5b919050565b60008060006060848603121561038057600080fd5b6103898461034f565b92506103976020850161034f565b91506103a56040850161034f565b90509250925092565b60005b838110156103c95781810151838201526020016103b1565b838111156103d8576000848401525b50505050565b600082516103f08184602087016103ae565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561042257600080fd5b815167ffffffffffffffff8082111561043a57600080fd5b818401915084601f83011261044e57600080fd5b815181811115610460576104606103fa565b604051601f8201601f19908116603f01168101908382118183101715610488576104886103fa565b816040528281528760208487010111156104a157600080fd5b6104b28360208301602088016103ae565b97965050505050505056fea2646970667358221220a70fce29b6e5fb440773cb2a94c85ba96b98c2b7d2d3f624750ec475578ed92764736f6c634300080c0033", +} + +// ChainCallLevel1ABI is the input ABI used to generate the binding from. +// Deprecated: Use ChainCallLevel1MetaData.ABI instead. +var ChainCallLevel1ABI = ChainCallLevel1MetaData.ABI + +// ChainCallLevel1Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ChainCallLevel1MetaData.Bin instead. +var ChainCallLevel1Bin = ChainCallLevel1MetaData.Bin + +// DeployChainCallLevel1 deploys a new Ethereum contract, binding an instance of ChainCallLevel1 to it. +func DeployChainCallLevel1(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChainCallLevel1, error) { + parsed, err := ChainCallLevel1MetaData.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(ChainCallLevel1Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ChainCallLevel1{ChainCallLevel1Caller: ChainCallLevel1Caller{contract: contract}, ChainCallLevel1Transactor: ChainCallLevel1Transactor{contract: contract}, ChainCallLevel1Filterer: ChainCallLevel1Filterer{contract: contract}}, nil +} + +// ChainCallLevel1 is an auto generated Go binding around an Ethereum contract. +type ChainCallLevel1 struct { + ChainCallLevel1Caller // Read-only binding to the contract + ChainCallLevel1Transactor // Write-only binding to the contract + ChainCallLevel1Filterer // Log filterer for contract events +} + +// ChainCallLevel1Caller is an auto generated read-only Go binding around an Ethereum contract. +type ChainCallLevel1Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel1Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ChainCallLevel1Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel1Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChainCallLevel1Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel1Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChainCallLevel1Session struct { + Contract *ChainCallLevel1 // 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 +} + +// ChainCallLevel1CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChainCallLevel1CallerSession struct { + Contract *ChainCallLevel1Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChainCallLevel1TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChainCallLevel1TransactorSession struct { + Contract *ChainCallLevel1Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChainCallLevel1Raw is an auto generated low-level Go binding around an Ethereum contract. +type ChainCallLevel1Raw struct { + Contract *ChainCallLevel1 // Generic contract binding to access the raw methods on +} + +// ChainCallLevel1CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChainCallLevel1CallerRaw struct { + Contract *ChainCallLevel1Caller // Generic read-only contract binding to access the raw methods on +} + +// ChainCallLevel1TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChainCallLevel1TransactorRaw struct { + Contract *ChainCallLevel1Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewChainCallLevel1 creates a new instance of ChainCallLevel1, bound to a specific deployed contract. +func NewChainCallLevel1(address common.Address, backend bind.ContractBackend) (*ChainCallLevel1, error) { + contract, err := bindChainCallLevel1(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ChainCallLevel1{ChainCallLevel1Caller: ChainCallLevel1Caller{contract: contract}, ChainCallLevel1Transactor: ChainCallLevel1Transactor{contract: contract}, ChainCallLevel1Filterer: ChainCallLevel1Filterer{contract: contract}}, nil +} + +// NewChainCallLevel1Caller creates a new read-only instance of ChainCallLevel1, bound to a specific deployed contract. +func NewChainCallLevel1Caller(address common.Address, caller bind.ContractCaller) (*ChainCallLevel1Caller, error) { + contract, err := bindChainCallLevel1(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel1Caller{contract: contract}, nil +} + +// NewChainCallLevel1Transactor creates a new write-only instance of ChainCallLevel1, bound to a specific deployed contract. +func NewChainCallLevel1Transactor(address common.Address, transactor bind.ContractTransactor) (*ChainCallLevel1Transactor, error) { + contract, err := bindChainCallLevel1(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel1Transactor{contract: contract}, nil +} + +// NewChainCallLevel1Filterer creates a new log filterer instance of ChainCallLevel1, bound to a specific deployed contract. +func NewChainCallLevel1Filterer(address common.Address, filterer bind.ContractFilterer) (*ChainCallLevel1Filterer, error) { + contract, err := bindChainCallLevel1(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChainCallLevel1Filterer{contract: contract}, nil +} + +// bindChainCallLevel1 binds a generic wrapper to an already deployed contract. +func bindChainCallLevel1(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ChainCallLevel1MetaData.GetAbi() + 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 (_ChainCallLevel1 *ChainCallLevel1Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel1.Contract.ChainCallLevel1Caller.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 (_ChainCallLevel1 *ChainCallLevel1Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.ChainCallLevel1Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel1 *ChainCallLevel1Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.ChainCallLevel1Transactor.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 (_ChainCallLevel1 *ChainCallLevel1CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel1.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 (_ChainCallLevel1 *ChainCallLevel1TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel1 *ChainCallLevel1TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.contract.Transact(opts, method, params...) +} + +// Exec is a paid mutator transaction binding the contract method 0xc023dcf3. +// +// Solidity: function exec(address level2Addr, address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel1 *ChainCallLevel1Transactor) Exec(opts *bind.TransactOpts, level2Addr common.Address, level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel1.contract.Transact(opts, "exec", level2Addr, level3Addr, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0xc023dcf3. +// +// Solidity: function exec(address level2Addr, address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel1 *ChainCallLevel1Session) Exec(level2Addr common.Address, level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.Exec(&_ChainCallLevel1.TransactOpts, level2Addr, level3Addr, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0xc023dcf3. +// +// Solidity: function exec(address level2Addr, address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel1 *ChainCallLevel1TransactorSession) Exec(level2Addr common.Address, level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel1.Contract.Exec(&_ChainCallLevel1.TransactOpts, level2Addr, level3Addr, level4Addr) +} diff --git a/test/contracts/bin/ChainCallLevel2/ChainCallLevel2.go b/test/contracts/bin/ChainCallLevel2/ChainCallLevel2.go new file mode 100644 index 0000000000..39e8fc0ea4 --- /dev/null +++ b/test/contracts/bin/ChainCallLevel2/ChainCallLevel2.go @@ -0,0 +1,255 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ChainCallLevel2 + +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 + _ = abi.ConvertType +) + +// ChainCallLevel2MetaData contains all meta data concerning the ChainCallLevel2 contract. +var ChainCallLevel2MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"level3Addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"level4Addr\",\"type\":\"address\"}],\"name\":\"exec\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"level3Addr\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"level4Addr\",\"type\":\"address\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"t\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061064e806100206000396000f3fe6080604052600436106100295760003560e01c8063d81e84231461002e578063ee2d011514610064575b600080fd5b34801561003a57600080fd5b5061004e6100493660046104a3565b610079565b60405161005b9190610506565b60405180910390f35b6100776100723660046104a3565b61029d565b005b6040516001600160a01b03828116602483015260609160009183919086169060440160408051601f198184030181529181526020820180516001600160e01b03166330af0bbf60e21b179052516100d09190610539565b600060405180830381855afa9150503d806000811461010b576040519150601f19603f3d011682016040523d82523d6000602084013e610110565b606091505b509092509050816101795760405162461bcd60e51b815260206004820152602860248201527f6661696c656420746f20706572666f726d207374617469632063616c6c20746f604482015267206c6576656c203360c01b60648201526084015b60405180910390fd5b8080602001905181019061018d919061056b565b60408051600481526024810182526020810180516001600160e01b0316631b53398f60e21b17905290519194506001600160a01b038616916101cf9190610539565b600060405180830381855afa9150503d806000811461020a576040519150601f19603f3d011682016040523d82523d6000602084013e61020f565b606091505b509092509050816102805760405162461bcd60e51b815260206004820152603560248201527f6661696c656420746f20706572666f726d207374617469632063616c6c20746f604482015274103632bb32b6101a10333937b6903632bb32b6101960591b6064820152608401610170565b80806020019051810190610294919061056b565b95945050505050565b6040516001600160a01b0382811660248301526000919084169060440160408051601f198184030181529181526020820180516001600160e01b03166335db093760e11b179052516102ef9190610539565b6000604051808303816000865af19150503d806000811461032c576040519150601f19603f3d011682016040523d82523d6000602084013e610331565b606091505b5050809150508061038e5760405162461bcd60e51b815260206004820152602160248201527f6661696c656420746f20706572666f726d2063616c6c20746f206c6576656c206044820152603360f81b6064820152608401610170565b6040516001600160a01b03838116602483015284169060440160408051601f198184030181529181526020820180516001600160e01b03166335db093760e11b179052516103dc9190610539565b600060405180830381855af49150503d8060008114610417576040519150601f19603f3d011682016040523d82523d6000602084013e61041c565b606091505b505080915050806104825760405162461bcd60e51b815260206004820152602a60248201527f6661696c656420746f20706572666f726d2064656c65676174652063616c6c20604482015269746f206c6576656c203360b01b6064820152608401610170565b505050565b80356001600160a01b038116811461049e57600080fd5b919050565b600080604083850312156104b657600080fd5b6104bf83610487565b91506104cd60208401610487565b90509250929050565b60005b838110156104f15781810151838201526020016104d9565b83811115610500576000848401525b50505050565b60208152600082518060208401526105258160408501602087016104d6565b601f01601f19169190910160400192915050565b6000825161054b8184602087016104d6565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561057d57600080fd5b815167ffffffffffffffff8082111561059557600080fd5b818401915084601f8301126105a957600080fd5b8151818111156105bb576105bb610555565b604051601f8201601f19908116603f011681019083821181831017156105e3576105e3610555565b816040528281528760208487010111156105fc57600080fd5b61060d8360208301602088016104d6565b97965050505050505056fea2646970667358221220bcf0de35efbb5279a8492473f9a7ed3e68ddf1cbd76bc1ae167505bf83c9042664736f6c634300080c0033", +} + +// ChainCallLevel2ABI is the input ABI used to generate the binding from. +// Deprecated: Use ChainCallLevel2MetaData.ABI instead. +var ChainCallLevel2ABI = ChainCallLevel2MetaData.ABI + +// ChainCallLevel2Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ChainCallLevel2MetaData.Bin instead. +var ChainCallLevel2Bin = ChainCallLevel2MetaData.Bin + +// DeployChainCallLevel2 deploys a new Ethereum contract, binding an instance of ChainCallLevel2 to it. +func DeployChainCallLevel2(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChainCallLevel2, error) { + parsed, err := ChainCallLevel2MetaData.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(ChainCallLevel2Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ChainCallLevel2{ChainCallLevel2Caller: ChainCallLevel2Caller{contract: contract}, ChainCallLevel2Transactor: ChainCallLevel2Transactor{contract: contract}, ChainCallLevel2Filterer: ChainCallLevel2Filterer{contract: contract}}, nil +} + +// ChainCallLevel2 is an auto generated Go binding around an Ethereum contract. +type ChainCallLevel2 struct { + ChainCallLevel2Caller // Read-only binding to the contract + ChainCallLevel2Transactor // Write-only binding to the contract + ChainCallLevel2Filterer // Log filterer for contract events +} + +// ChainCallLevel2Caller is an auto generated read-only Go binding around an Ethereum contract. +type ChainCallLevel2Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel2Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ChainCallLevel2Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel2Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChainCallLevel2Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel2Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChainCallLevel2Session struct { + Contract *ChainCallLevel2 // 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 +} + +// ChainCallLevel2CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChainCallLevel2CallerSession struct { + Contract *ChainCallLevel2Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChainCallLevel2TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChainCallLevel2TransactorSession struct { + Contract *ChainCallLevel2Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChainCallLevel2Raw is an auto generated low-level Go binding around an Ethereum contract. +type ChainCallLevel2Raw struct { + Contract *ChainCallLevel2 // Generic contract binding to access the raw methods on +} + +// ChainCallLevel2CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChainCallLevel2CallerRaw struct { + Contract *ChainCallLevel2Caller // Generic read-only contract binding to access the raw methods on +} + +// ChainCallLevel2TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChainCallLevel2TransactorRaw struct { + Contract *ChainCallLevel2Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewChainCallLevel2 creates a new instance of ChainCallLevel2, bound to a specific deployed contract. +func NewChainCallLevel2(address common.Address, backend bind.ContractBackend) (*ChainCallLevel2, error) { + contract, err := bindChainCallLevel2(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ChainCallLevel2{ChainCallLevel2Caller: ChainCallLevel2Caller{contract: contract}, ChainCallLevel2Transactor: ChainCallLevel2Transactor{contract: contract}, ChainCallLevel2Filterer: ChainCallLevel2Filterer{contract: contract}}, nil +} + +// NewChainCallLevel2Caller creates a new read-only instance of ChainCallLevel2, bound to a specific deployed contract. +func NewChainCallLevel2Caller(address common.Address, caller bind.ContractCaller) (*ChainCallLevel2Caller, error) { + contract, err := bindChainCallLevel2(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel2Caller{contract: contract}, nil +} + +// NewChainCallLevel2Transactor creates a new write-only instance of ChainCallLevel2, bound to a specific deployed contract. +func NewChainCallLevel2Transactor(address common.Address, transactor bind.ContractTransactor) (*ChainCallLevel2Transactor, error) { + contract, err := bindChainCallLevel2(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel2Transactor{contract: contract}, nil +} + +// NewChainCallLevel2Filterer creates a new log filterer instance of ChainCallLevel2, bound to a specific deployed contract. +func NewChainCallLevel2Filterer(address common.Address, filterer bind.ContractFilterer) (*ChainCallLevel2Filterer, error) { + contract, err := bindChainCallLevel2(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChainCallLevel2Filterer{contract: contract}, nil +} + +// bindChainCallLevel2 binds a generic wrapper to an already deployed contract. +func bindChainCallLevel2(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ChainCallLevel2MetaData.GetAbi() + 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 (_ChainCallLevel2 *ChainCallLevel2Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel2.Contract.ChainCallLevel2Caller.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 (_ChainCallLevel2 *ChainCallLevel2Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.ChainCallLevel2Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel2 *ChainCallLevel2Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.ChainCallLevel2Transactor.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 (_ChainCallLevel2 *ChainCallLevel2CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel2.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 (_ChainCallLevel2 *ChainCallLevel2TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel2 *ChainCallLevel2TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.contract.Transact(opts, method, params...) +} + +// Get is a free data retrieval call binding the contract method 0xd81e8423. +// +// Solidity: function get(address level3Addr, address level4Addr) view returns(string t) +func (_ChainCallLevel2 *ChainCallLevel2Caller) Get(opts *bind.CallOpts, level3Addr common.Address, level4Addr common.Address) (string, error) { + var out []interface{} + err := _ChainCallLevel2.contract.Call(opts, &out, "get", level3Addr, level4Addr) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Get is a free data retrieval call binding the contract method 0xd81e8423. +// +// Solidity: function get(address level3Addr, address level4Addr) view returns(string t) +func (_ChainCallLevel2 *ChainCallLevel2Session) Get(level3Addr common.Address, level4Addr common.Address) (string, error) { + return _ChainCallLevel2.Contract.Get(&_ChainCallLevel2.CallOpts, level3Addr, level4Addr) +} + +// Get is a free data retrieval call binding the contract method 0xd81e8423. +// +// Solidity: function get(address level3Addr, address level4Addr) view returns(string t) +func (_ChainCallLevel2 *ChainCallLevel2CallerSession) Get(level3Addr common.Address, level4Addr common.Address) (string, error) { + return _ChainCallLevel2.Contract.Get(&_ChainCallLevel2.CallOpts, level3Addr, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0xee2d0115. +// +// Solidity: function exec(address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel2 *ChainCallLevel2Transactor) Exec(opts *bind.TransactOpts, level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel2.contract.Transact(opts, "exec", level3Addr, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0xee2d0115. +// +// Solidity: function exec(address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel2 *ChainCallLevel2Session) Exec(level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.Exec(&_ChainCallLevel2.TransactOpts, level3Addr, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0xee2d0115. +// +// Solidity: function exec(address level3Addr, address level4Addr) payable returns() +func (_ChainCallLevel2 *ChainCallLevel2TransactorSession) Exec(level3Addr common.Address, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel2.Contract.Exec(&_ChainCallLevel2.TransactOpts, level3Addr, level4Addr) +} diff --git a/test/contracts/bin/ChainCallLevel3/ChainCallLevel3.go b/test/contracts/bin/ChainCallLevel3/ChainCallLevel3.go new file mode 100644 index 0000000000..0e7e6219e6 --- /dev/null +++ b/test/contracts/bin/ChainCallLevel3/ChainCallLevel3.go @@ -0,0 +1,255 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ChainCallLevel3 + +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 + _ = abi.ConvertType +) + +// ChainCallLevel3MetaData contains all meta data concerning the ChainCallLevel3 contract. +var ChainCallLevel3MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"level4Addr\",\"type\":\"address\"}],\"name\":\"exec\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"level4Addr\",\"type\":\"address\"}],\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"t\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506104f6806100206000396000f3fe6080604052600436106100295760003560e01c80636bb6126e1461002e578063c2bc2efc14610043575b600080fd5b61004161003c36600461034e565b610079565b005b34801561004f57600080fd5b5061006361005e36600461034e565b610247565b60405161007091906103ae565b60405180910390f35b60408051600481526024810182526020810180516001600160e01b03166330703a7160e21b17905290516000916001600160a01b038416916100bb91906103e1565b6000604051808303816000865af19150503d80600081146100f8576040519150601f19603f3d011682016040523d82523d6000602084013e6100fd565b606091505b5050809150508061015f5760405162461bcd60e51b815260206004820152602160248201527f6661696c656420746f20706572666f726d2063616c6c20746f206c6576656c206044820152600d60fa1b60648201526084015b60405180910390fd5b60408051600481526024810182526020810180516001600160e01b03166330703a7160e21b17905290516001600160a01b0384169161019d916103e1565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b505080915050806102435760405162461bcd60e51b815260206004820152602a60248201527f6661696c656420746f20706572666f726d2064656c65676174652063616c6c206044820152691d1bc81b195d995b080d60b21b6064820152608401610156565b5050565b60408051600481526024810182526020810180516001600160e01b0316631b53398f60e21b179052905160609160009183916001600160a01b0386169161028e91906103e1565b600060405180830381855afa9150503d80600081146102c9576040519150601f19603f3d011682016040523d82523d6000602084013e6102ce565b606091505b509092509050816103325760405162461bcd60e51b815260206004820152602860248201527f6661696c656420746f20706572666f726d207374617469632063616c6c20746f604482015267081b195d995b080d60c21b6064820152608401610156565b808060200190518101906103469190610413565b949350505050565b60006020828403121561036057600080fd5b81356001600160a01b038116811461037757600080fd5b9392505050565b60005b83811015610399578181015183820152602001610381565b838111156103a8576000848401525b50505050565b60208152600082518060208401526103cd81604085016020870161037e565b601f01601f19169190910160400192915050565b600082516103f381846020870161037e565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561042557600080fd5b815167ffffffffffffffff8082111561043d57600080fd5b818401915084601f83011261045157600080fd5b815181811115610463576104636103fd565b604051601f8201601f19908116603f0116810190838211818310171561048b5761048b6103fd565b816040528281528760208487010111156104a457600080fd5b6104b583602083016020880161037e565b97965050505050505056fea26469706673582212209bedf8d59efd5de6abd239994136138fbe5555047e0cce461bf5853bf28167db64736f6c634300080c0033", +} + +// ChainCallLevel3ABI is the input ABI used to generate the binding from. +// Deprecated: Use ChainCallLevel3MetaData.ABI instead. +var ChainCallLevel3ABI = ChainCallLevel3MetaData.ABI + +// ChainCallLevel3Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ChainCallLevel3MetaData.Bin instead. +var ChainCallLevel3Bin = ChainCallLevel3MetaData.Bin + +// DeployChainCallLevel3 deploys a new Ethereum contract, binding an instance of ChainCallLevel3 to it. +func DeployChainCallLevel3(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChainCallLevel3, error) { + parsed, err := ChainCallLevel3MetaData.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(ChainCallLevel3Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ChainCallLevel3{ChainCallLevel3Caller: ChainCallLevel3Caller{contract: contract}, ChainCallLevel3Transactor: ChainCallLevel3Transactor{contract: contract}, ChainCallLevel3Filterer: ChainCallLevel3Filterer{contract: contract}}, nil +} + +// ChainCallLevel3 is an auto generated Go binding around an Ethereum contract. +type ChainCallLevel3 struct { + ChainCallLevel3Caller // Read-only binding to the contract + ChainCallLevel3Transactor // Write-only binding to the contract + ChainCallLevel3Filterer // Log filterer for contract events +} + +// ChainCallLevel3Caller is an auto generated read-only Go binding around an Ethereum contract. +type ChainCallLevel3Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel3Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ChainCallLevel3Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel3Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChainCallLevel3Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel3Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChainCallLevel3Session struct { + Contract *ChainCallLevel3 // 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 +} + +// ChainCallLevel3CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChainCallLevel3CallerSession struct { + Contract *ChainCallLevel3Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChainCallLevel3TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChainCallLevel3TransactorSession struct { + Contract *ChainCallLevel3Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChainCallLevel3Raw is an auto generated low-level Go binding around an Ethereum contract. +type ChainCallLevel3Raw struct { + Contract *ChainCallLevel3 // Generic contract binding to access the raw methods on +} + +// ChainCallLevel3CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChainCallLevel3CallerRaw struct { + Contract *ChainCallLevel3Caller // Generic read-only contract binding to access the raw methods on +} + +// ChainCallLevel3TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChainCallLevel3TransactorRaw struct { + Contract *ChainCallLevel3Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewChainCallLevel3 creates a new instance of ChainCallLevel3, bound to a specific deployed contract. +func NewChainCallLevel3(address common.Address, backend bind.ContractBackend) (*ChainCallLevel3, error) { + contract, err := bindChainCallLevel3(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ChainCallLevel3{ChainCallLevel3Caller: ChainCallLevel3Caller{contract: contract}, ChainCallLevel3Transactor: ChainCallLevel3Transactor{contract: contract}, ChainCallLevel3Filterer: ChainCallLevel3Filterer{contract: contract}}, nil +} + +// NewChainCallLevel3Caller creates a new read-only instance of ChainCallLevel3, bound to a specific deployed contract. +func NewChainCallLevel3Caller(address common.Address, caller bind.ContractCaller) (*ChainCallLevel3Caller, error) { + contract, err := bindChainCallLevel3(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel3Caller{contract: contract}, nil +} + +// NewChainCallLevel3Transactor creates a new write-only instance of ChainCallLevel3, bound to a specific deployed contract. +func NewChainCallLevel3Transactor(address common.Address, transactor bind.ContractTransactor) (*ChainCallLevel3Transactor, error) { + contract, err := bindChainCallLevel3(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel3Transactor{contract: contract}, nil +} + +// NewChainCallLevel3Filterer creates a new log filterer instance of ChainCallLevel3, bound to a specific deployed contract. +func NewChainCallLevel3Filterer(address common.Address, filterer bind.ContractFilterer) (*ChainCallLevel3Filterer, error) { + contract, err := bindChainCallLevel3(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChainCallLevel3Filterer{contract: contract}, nil +} + +// bindChainCallLevel3 binds a generic wrapper to an already deployed contract. +func bindChainCallLevel3(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ChainCallLevel3MetaData.GetAbi() + 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 (_ChainCallLevel3 *ChainCallLevel3Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel3.Contract.ChainCallLevel3Caller.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 (_ChainCallLevel3 *ChainCallLevel3Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.ChainCallLevel3Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel3 *ChainCallLevel3Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.ChainCallLevel3Transactor.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 (_ChainCallLevel3 *ChainCallLevel3CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel3.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 (_ChainCallLevel3 *ChainCallLevel3TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel3 *ChainCallLevel3TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.contract.Transact(opts, method, params...) +} + +// Get is a free data retrieval call binding the contract method 0xc2bc2efc. +// +// Solidity: function get(address level4Addr) view returns(string t) +func (_ChainCallLevel3 *ChainCallLevel3Caller) Get(opts *bind.CallOpts, level4Addr common.Address) (string, error) { + var out []interface{} + err := _ChainCallLevel3.contract.Call(opts, &out, "get", level4Addr) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Get is a free data retrieval call binding the contract method 0xc2bc2efc. +// +// Solidity: function get(address level4Addr) view returns(string t) +func (_ChainCallLevel3 *ChainCallLevel3Session) Get(level4Addr common.Address) (string, error) { + return _ChainCallLevel3.Contract.Get(&_ChainCallLevel3.CallOpts, level4Addr) +} + +// Get is a free data retrieval call binding the contract method 0xc2bc2efc. +// +// Solidity: function get(address level4Addr) view returns(string t) +func (_ChainCallLevel3 *ChainCallLevel3CallerSession) Get(level4Addr common.Address) (string, error) { + return _ChainCallLevel3.Contract.Get(&_ChainCallLevel3.CallOpts, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0x6bb6126e. +// +// Solidity: function exec(address level4Addr) payable returns() +func (_ChainCallLevel3 *ChainCallLevel3Transactor) Exec(opts *bind.TransactOpts, level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel3.contract.Transact(opts, "exec", level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0x6bb6126e. +// +// Solidity: function exec(address level4Addr) payable returns() +func (_ChainCallLevel3 *ChainCallLevel3Session) Exec(level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.Exec(&_ChainCallLevel3.TransactOpts, level4Addr) +} + +// Exec is a paid mutator transaction binding the contract method 0x6bb6126e. +// +// Solidity: function exec(address level4Addr) payable returns() +func (_ChainCallLevel3 *ChainCallLevel3TransactorSession) Exec(level4Addr common.Address) (*types.Transaction, error) { + return _ChainCallLevel3.Contract.Exec(&_ChainCallLevel3.TransactOpts, level4Addr) +} diff --git a/test/contracts/bin/ChainCallLevel4/ChainCallLevel4.go b/test/contracts/bin/ChainCallLevel4/ChainCallLevel4.go new file mode 100644 index 0000000000..513ef6cc7d --- /dev/null +++ b/test/contracts/bin/ChainCallLevel4/ChainCallLevel4.go @@ -0,0 +1,255 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ChainCallLevel4 + +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 + _ = abi.ConvertType +) + +// ChainCallLevel4MetaData contains all meta data concerning the ChainCallLevel4 contract. +var ChainCallLevel4MetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"exec\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"t\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610108806100206000396000f3fe60806040526004361060265760003560e01c80636d4ce63c14602b578063c1c0e9c4146064575b600080fd5b348015603657600080fd5b50604080518082018252600481526361686f7960e01b60208201529051605b91906080565b60405180910390f35b607e600080546001600160a01b0319163317905534600155565b005b600060208083528351808285015260005b8181101560ab578581018301518582016040015282016091565b8181111560bc576000604083870101525b50601f01601f191692909201604001939250505056fea26469706673582212207c7fc2b6008207a67e9e5557e853391335de750d1de5dcadc457558a526d437a64736f6c634300080c0033", +} + +// ChainCallLevel4ABI is the input ABI used to generate the binding from. +// Deprecated: Use ChainCallLevel4MetaData.ABI instead. +var ChainCallLevel4ABI = ChainCallLevel4MetaData.ABI + +// ChainCallLevel4Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ChainCallLevel4MetaData.Bin instead. +var ChainCallLevel4Bin = ChainCallLevel4MetaData.Bin + +// DeployChainCallLevel4 deploys a new Ethereum contract, binding an instance of ChainCallLevel4 to it. +func DeployChainCallLevel4(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ChainCallLevel4, error) { + parsed, err := ChainCallLevel4MetaData.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(ChainCallLevel4Bin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &ChainCallLevel4{ChainCallLevel4Caller: ChainCallLevel4Caller{contract: contract}, ChainCallLevel4Transactor: ChainCallLevel4Transactor{contract: contract}, ChainCallLevel4Filterer: ChainCallLevel4Filterer{contract: contract}}, nil +} + +// ChainCallLevel4 is an auto generated Go binding around an Ethereum contract. +type ChainCallLevel4 struct { + ChainCallLevel4Caller // Read-only binding to the contract + ChainCallLevel4Transactor // Write-only binding to the contract + ChainCallLevel4Filterer // Log filterer for contract events +} + +// ChainCallLevel4Caller is an auto generated read-only Go binding around an Ethereum contract. +type ChainCallLevel4Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel4Transactor is an auto generated write-only Go binding around an Ethereum contract. +type ChainCallLevel4Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel4Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ChainCallLevel4Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ChainCallLevel4Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ChainCallLevel4Session struct { + Contract *ChainCallLevel4 // 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 +} + +// ChainCallLevel4CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ChainCallLevel4CallerSession struct { + Contract *ChainCallLevel4Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ChainCallLevel4TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ChainCallLevel4TransactorSession struct { + Contract *ChainCallLevel4Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ChainCallLevel4Raw is an auto generated low-level Go binding around an Ethereum contract. +type ChainCallLevel4Raw struct { + Contract *ChainCallLevel4 // Generic contract binding to access the raw methods on +} + +// ChainCallLevel4CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ChainCallLevel4CallerRaw struct { + Contract *ChainCallLevel4Caller // Generic read-only contract binding to access the raw methods on +} + +// ChainCallLevel4TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ChainCallLevel4TransactorRaw struct { + Contract *ChainCallLevel4Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewChainCallLevel4 creates a new instance of ChainCallLevel4, bound to a specific deployed contract. +func NewChainCallLevel4(address common.Address, backend bind.ContractBackend) (*ChainCallLevel4, error) { + contract, err := bindChainCallLevel4(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &ChainCallLevel4{ChainCallLevel4Caller: ChainCallLevel4Caller{contract: contract}, ChainCallLevel4Transactor: ChainCallLevel4Transactor{contract: contract}, ChainCallLevel4Filterer: ChainCallLevel4Filterer{contract: contract}}, nil +} + +// NewChainCallLevel4Caller creates a new read-only instance of ChainCallLevel4, bound to a specific deployed contract. +func NewChainCallLevel4Caller(address common.Address, caller bind.ContractCaller) (*ChainCallLevel4Caller, error) { + contract, err := bindChainCallLevel4(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel4Caller{contract: contract}, nil +} + +// NewChainCallLevel4Transactor creates a new write-only instance of ChainCallLevel4, bound to a specific deployed contract. +func NewChainCallLevel4Transactor(address common.Address, transactor bind.ContractTransactor) (*ChainCallLevel4Transactor, error) { + contract, err := bindChainCallLevel4(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ChainCallLevel4Transactor{contract: contract}, nil +} + +// NewChainCallLevel4Filterer creates a new log filterer instance of ChainCallLevel4, bound to a specific deployed contract. +func NewChainCallLevel4Filterer(address common.Address, filterer bind.ContractFilterer) (*ChainCallLevel4Filterer, error) { + contract, err := bindChainCallLevel4(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ChainCallLevel4Filterer{contract: contract}, nil +} + +// bindChainCallLevel4 binds a generic wrapper to an already deployed contract. +func bindChainCallLevel4(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ChainCallLevel4MetaData.GetAbi() + 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 (_ChainCallLevel4 *ChainCallLevel4Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel4.Contract.ChainCallLevel4Caller.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 (_ChainCallLevel4 *ChainCallLevel4Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel4.Contract.ChainCallLevel4Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel4 *ChainCallLevel4Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel4.Contract.ChainCallLevel4Transactor.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 (_ChainCallLevel4 *ChainCallLevel4CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _ChainCallLevel4.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 (_ChainCallLevel4 *ChainCallLevel4TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel4.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_ChainCallLevel4 *ChainCallLevel4TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _ChainCallLevel4.Contract.contract.Transact(opts, method, params...) +} + +// Get is a free data retrieval call binding the contract method 0x6d4ce63c. +// +// Solidity: function get() pure returns(string t) +func (_ChainCallLevel4 *ChainCallLevel4Caller) Get(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _ChainCallLevel4.contract.Call(opts, &out, "get") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Get is a free data retrieval call binding the contract method 0x6d4ce63c. +// +// Solidity: function get() pure returns(string t) +func (_ChainCallLevel4 *ChainCallLevel4Session) Get() (string, error) { + return _ChainCallLevel4.Contract.Get(&_ChainCallLevel4.CallOpts) +} + +// Get is a free data retrieval call binding the contract method 0x6d4ce63c. +// +// Solidity: function get() pure returns(string t) +func (_ChainCallLevel4 *ChainCallLevel4CallerSession) Get() (string, error) { + return _ChainCallLevel4.Contract.Get(&_ChainCallLevel4.CallOpts) +} + +// Exec is a paid mutator transaction binding the contract method 0xc1c0e9c4. +// +// Solidity: function exec() payable returns() +func (_ChainCallLevel4 *ChainCallLevel4Transactor) Exec(opts *bind.TransactOpts) (*types.Transaction, error) { + return _ChainCallLevel4.contract.Transact(opts, "exec") +} + +// Exec is a paid mutator transaction binding the contract method 0xc1c0e9c4. +// +// Solidity: function exec() payable returns() +func (_ChainCallLevel4 *ChainCallLevel4Session) Exec() (*types.Transaction, error) { + return _ChainCallLevel4.Contract.Exec(&_ChainCallLevel4.TransactOpts) +} + +// Exec is a paid mutator transaction binding the contract method 0xc1c0e9c4. +// +// Solidity: function exec() payable returns() +func (_ChainCallLevel4 *ChainCallLevel4TransactorSession) Exec() (*types.Transaction, error) { + return _ChainCallLevel4.Contract.Exec(&_ChainCallLevel4.TransactOpts) +} diff --git a/test/contracts/bin/Counter/Counter.go b/test/contracts/bin/Counter/Counter.go index 139c64bb8c..161abaa90a 100644 --- a/test/contracts/bin/Counter/Counter.go +++ b/test/contracts/bin/Counter/Counter.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // CounterMetaData contains all meta data concerning the Counter contract. @@ -156,11 +157,11 @@ func NewCounterFilterer(address common.Address, filterer bind.ContractFilterer) // bindCounter binds a generic wrapper to an already deployed contract. func bindCounter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(CounterABI)) + parsed, err := CounterMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Creates/Creates.go b/test/contracts/bin/Creates/Creates.go new file mode 100644 index 0000000000..af2bf2e773 --- /dev/null +++ b/test/contracts/bin/Creates/Creates.go @@ -0,0 +1,360 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package Creates + +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 + _ = abi.ConvertType +) + +// CreatesMetaData contains all meta data concerning the Creates contract. +var CreatesMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"}],\"name\":\"add\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"bytecode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"opCreate\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"bytecode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"opCreate2\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"bytecode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"opCreate2Complex\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"bytecode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"opCreate2Value\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"bytecode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"opCreateValue\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sendValue\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610369806100206000396000f3fe6080604052600436106100705760003560e01c8063771602f71161004e578063771602f7146100d0578063b88c4aa9146100fe578063c935aee414610111578063e3306a251461015057600080fd5b806327c845dc146100755780633c77eba3146100805780635b8e9959146100b0575b600080fd5b61007e34600155565b005b61009361008e366004610236565b610170565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100bc57600080fd5b506100936100cb366004610236565b610187565b3480156100dc57600080fd5b506100f06100eb3660046102eb565b61019d565b6040519081526020016100a7565b61009361010c366004610236565b6101b0565b34801561011d57600080fd5b5061013161012c366004610236565b6101cb565b604080516001600160a01b0390931683526020830191909152016100a7565b34801561015c57600080fd5b5061009361016b366004610236565b610208565b6000808260a06101f4f06000819055949350505050565b6000808260a06000f06000819055949350505050565b60006101a9828461030d565b9392505050565b600080620555558360a061012cf56000819055949350505050565b60008060006101dc6001600261019d565b90506000600285602088016000f59050806000556101fc6002600461019d565b90969095509350505050565b60008060028360a06000f56000819055949350505050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561024957600080fd5b823567ffffffffffffffff8082111561026157600080fd5b818501915085601f83011261027557600080fd5b81358181111561028757610287610220565b604051601f8201601f19908116603f011681019083821181831017156102af576102af610220565b816040528281528860208487010111156102c857600080fd5b826020860160208301376000602093820184015298969091013596505050505050565b600080604083850312156102fe57600080fd5b50508035926020909101359150565b6000821982111561032e57634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220cdc0e0bdc2487139b3aa0666f32d3f0ed1e40a81659b28e6dea427224cc6104f64736f6c634300080c0033", +} + +// CreatesABI is the input ABI used to generate the binding from. +// Deprecated: Use CreatesMetaData.ABI instead. +var CreatesABI = CreatesMetaData.ABI + +// CreatesBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use CreatesMetaData.Bin instead. +var CreatesBin = CreatesMetaData.Bin + +// DeployCreates deploys a new Ethereum contract, binding an instance of Creates to it. +func DeployCreates(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Creates, error) { + parsed, err := CreatesMetaData.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(CreatesBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Creates{CreatesCaller: CreatesCaller{contract: contract}, CreatesTransactor: CreatesTransactor{contract: contract}, CreatesFilterer: CreatesFilterer{contract: contract}}, nil +} + +// Creates is an auto generated Go binding around an Ethereum contract. +type Creates struct { + CreatesCaller // Read-only binding to the contract + CreatesTransactor // Write-only binding to the contract + CreatesFilterer // Log filterer for contract events +} + +// CreatesCaller is an auto generated read-only Go binding around an Ethereum contract. +type CreatesCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CreatesTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CreatesTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CreatesFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CreatesFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CreatesSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CreatesSession struct { + Contract *Creates // 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 +} + +// CreatesCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CreatesCallerSession struct { + Contract *CreatesCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CreatesTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CreatesTransactorSession struct { + Contract *CreatesTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CreatesRaw is an auto generated low-level Go binding around an Ethereum contract. +type CreatesRaw struct { + Contract *Creates // Generic contract binding to access the raw methods on +} + +// CreatesCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CreatesCallerRaw struct { + Contract *CreatesCaller // Generic read-only contract binding to access the raw methods on +} + +// CreatesTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CreatesTransactorRaw struct { + Contract *CreatesTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCreates creates a new instance of Creates, bound to a specific deployed contract. +func NewCreates(address common.Address, backend bind.ContractBackend) (*Creates, error) { + contract, err := bindCreates(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Creates{CreatesCaller: CreatesCaller{contract: contract}, CreatesTransactor: CreatesTransactor{contract: contract}, CreatesFilterer: CreatesFilterer{contract: contract}}, nil +} + +// NewCreatesCaller creates a new read-only instance of Creates, bound to a specific deployed contract. +func NewCreatesCaller(address common.Address, caller bind.ContractCaller) (*CreatesCaller, error) { + contract, err := bindCreates(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CreatesCaller{contract: contract}, nil +} + +// NewCreatesTransactor creates a new write-only instance of Creates, bound to a specific deployed contract. +func NewCreatesTransactor(address common.Address, transactor bind.ContractTransactor) (*CreatesTransactor, error) { + contract, err := bindCreates(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CreatesTransactor{contract: contract}, nil +} + +// NewCreatesFilterer creates a new log filterer instance of Creates, bound to a specific deployed contract. +func NewCreatesFilterer(address common.Address, filterer bind.ContractFilterer) (*CreatesFilterer, error) { + contract, err := bindCreates(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CreatesFilterer{contract: contract}, nil +} + +// bindCreates binds a generic wrapper to an already deployed contract. +func bindCreates(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CreatesMetaData.GetAbi() + 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 (_Creates *CreatesRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Creates.Contract.CreatesCaller.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 (_Creates *CreatesRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Creates.Contract.CreatesTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Creates *CreatesRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Creates.Contract.CreatesTransactor.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 (_Creates *CreatesCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Creates.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 (_Creates *CreatesTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Creates.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Creates *CreatesTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Creates.Contract.contract.Transact(opts, method, params...) +} + +// Add is a free data retrieval call binding the contract method 0x771602f7. +// +// Solidity: function add(uint256 a, uint256 b) pure returns(uint256) +func (_Creates *CreatesCaller) Add(opts *bind.CallOpts, a *big.Int, b *big.Int) (*big.Int, error) { + var out []interface{} + err := _Creates.contract.Call(opts, &out, "add", a, b) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Add is a free data retrieval call binding the contract method 0x771602f7. +// +// Solidity: function add(uint256 a, uint256 b) pure returns(uint256) +func (_Creates *CreatesSession) Add(a *big.Int, b *big.Int) (*big.Int, error) { + return _Creates.Contract.Add(&_Creates.CallOpts, a, b) +} + +// Add is a free data retrieval call binding the contract method 0x771602f7. +// +// Solidity: function add(uint256 a, uint256 b) pure returns(uint256) +func (_Creates *CreatesCallerSession) Add(a *big.Int, b *big.Int) (*big.Int, error) { + return _Creates.Contract.Add(&_Creates.CallOpts, a, b) +} + +// OpCreate is a paid mutator transaction binding the contract method 0x5b8e9959. +// +// Solidity: function opCreate(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesTransactor) OpCreate(opts *bind.TransactOpts, bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "opCreate", bytecode, length) +} + +// OpCreate is a paid mutator transaction binding the contract method 0x5b8e9959. +// +// Solidity: function opCreate(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesSession) OpCreate(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate is a paid mutator transaction binding the contract method 0x5b8e9959. +// +// Solidity: function opCreate(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesTransactorSession) OpCreate(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2 is a paid mutator transaction binding the contract method 0xe3306a25. +// +// Solidity: function opCreate2(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesTransactor) OpCreate2(opts *bind.TransactOpts, bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "opCreate2", bytecode, length) +} + +// OpCreate2 is a paid mutator transaction binding the contract method 0xe3306a25. +// +// Solidity: function opCreate2(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesSession) OpCreate2(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2 is a paid mutator transaction binding the contract method 0xe3306a25. +// +// Solidity: function opCreate2(bytes bytecode, uint256 length) returns(address) +func (_Creates *CreatesTransactorSession) OpCreate2(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2Complex is a paid mutator transaction binding the contract method 0xc935aee4. +// +// Solidity: function opCreate2Complex(bytes bytecode, uint256 length) returns(address, uint256) +func (_Creates *CreatesTransactor) OpCreate2Complex(opts *bind.TransactOpts, bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "opCreate2Complex", bytecode, length) +} + +// OpCreate2Complex is a paid mutator transaction binding the contract method 0xc935aee4. +// +// Solidity: function opCreate2Complex(bytes bytecode, uint256 length) returns(address, uint256) +func (_Creates *CreatesSession) OpCreate2Complex(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2Complex(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2Complex is a paid mutator transaction binding the contract method 0xc935aee4. +// +// Solidity: function opCreate2Complex(bytes bytecode, uint256 length) returns(address, uint256) +func (_Creates *CreatesTransactorSession) OpCreate2Complex(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2Complex(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2Value is a paid mutator transaction binding the contract method 0xb88c4aa9. +// +// Solidity: function opCreate2Value(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesTransactor) OpCreate2Value(opts *bind.TransactOpts, bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "opCreate2Value", bytecode, length) +} + +// OpCreate2Value is a paid mutator transaction binding the contract method 0xb88c4aa9. +// +// Solidity: function opCreate2Value(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesSession) OpCreate2Value(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2Value(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreate2Value is a paid mutator transaction binding the contract method 0xb88c4aa9. +// +// Solidity: function opCreate2Value(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesTransactorSession) OpCreate2Value(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreate2Value(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreateValue is a paid mutator transaction binding the contract method 0x3c77eba3. +// +// Solidity: function opCreateValue(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesTransactor) OpCreateValue(opts *bind.TransactOpts, bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "opCreateValue", bytecode, length) +} + +// OpCreateValue is a paid mutator transaction binding the contract method 0x3c77eba3. +// +// Solidity: function opCreateValue(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesSession) OpCreateValue(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreateValue(&_Creates.TransactOpts, bytecode, length) +} + +// OpCreateValue is a paid mutator transaction binding the contract method 0x3c77eba3. +// +// Solidity: function opCreateValue(bytes bytecode, uint256 length) payable returns(address) +func (_Creates *CreatesTransactorSession) OpCreateValue(bytecode []byte, length *big.Int) (*types.Transaction, error) { + return _Creates.Contract.OpCreateValue(&_Creates.TransactOpts, bytecode, length) +} + +// SendValue is a paid mutator transaction binding the contract method 0x27c845dc. +// +// Solidity: function sendValue() payable returns() +func (_Creates *CreatesTransactor) SendValue(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Creates.contract.Transact(opts, "sendValue") +} + +// SendValue is a paid mutator transaction binding the contract method 0x27c845dc. +// +// Solidity: function sendValue() payable returns() +func (_Creates *CreatesSession) SendValue() (*types.Transaction, error) { + return _Creates.Contract.SendValue(&_Creates.TransactOpts) +} + +// SendValue is a paid mutator transaction binding the contract method 0x27c845dc. +// +// Solidity: function sendValue() payable returns() +func (_Creates *CreatesTransactorSession) SendValue() (*types.Transaction, error) { + return _Creates.Contract.SendValue(&_Creates.TransactOpts) +} diff --git a/test/contracts/bin/DelegatecallReceiver/DelegatecallReceiver.go b/test/contracts/bin/DelegatecallReceiver/DelegatecallReceiver.go deleted file mode 100644 index 894e5b1286..0000000000 --- a/test/contracts/bin/DelegatecallReceiver/DelegatecallReceiver.go +++ /dev/null @@ -1,262 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package DelegatecallReceiver - -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 -) - -// DelegatecallReceiverMetaData contains all meta data concerning the DelegatecallReceiver contract. -var DelegatecallReceiverMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"entrypoint\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"expectedSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610415806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631754dba51461003b578063a65d69d41461006a575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b610072610074565b005b6000546001600160a01b03163381149061008f9060146100e4565b61009a3360146100e4565b6040516020016100ab9291906102b7565b604051602081830303815290604052906100e15760405162461bcd60e51b81526004016100d8919061031c565b60405180910390fd5b50565b606060006100f3836002610365565b6100fe906002610384565b67ffffffffffffffff8111156101165761011661039c565b6040519080825280601f01601f191660200182016040528015610140576020820181803683370190505b509050600360fc1b8160008151811061015b5761015b6103b2565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061018a5761018a6103b2565b60200101906001600160f81b031916908160001a90535060006101ae846002610365565b6101b9906001610384565b90505b6001811115610231576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106101ed576101ed6103b2565b1a60f81b828281518110610203576102036103b2565b60200101906001600160f81b031916908160001a90535060049490941c9361022a816103c8565b90506101bc565b5083156102805760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016100d8565b9392505050565b60005b838110156102a257818101518382015260200161028a565b838111156102b1576000848401525b50505050565b6e032bc3832b1ba32b229b2b73232b91608d1b8152600083516102e181600f850160208801610287565b6e01030b1ba3ab0b61039b2b73232b91608d1b600f91840191820152835161031081601e840160208801610287565b01601e01949350505050565b602081526000825180602084015261033b816040850160208701610287565b601f01601f19169190910160400192915050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561037f5761037f61034f565b500290565b600082198211156103975761039761034f565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000816103d7576103d761034f565b50600019019056fea264697066735822122021f68a56920052d98a209122db94525247e8b3b43872363d5e85c3529943feed64736f6c634300080c0033", -} - -// DelegatecallReceiverABI is the input ABI used to generate the binding from. -// Deprecated: Use DelegatecallReceiverMetaData.ABI instead. -var DelegatecallReceiverABI = DelegatecallReceiverMetaData.ABI - -// DelegatecallReceiverBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use DelegatecallReceiverMetaData.Bin instead. -var DelegatecallReceiverBin = DelegatecallReceiverMetaData.Bin - -// DeployDelegatecallReceiver deploys a new Ethereum contract, binding an instance of DelegatecallReceiver to it. -func DeployDelegatecallReceiver(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DelegatecallReceiver, error) { - parsed, err := DelegatecallReceiverMetaData.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(DelegatecallReceiverBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &DelegatecallReceiver{DelegatecallReceiverCaller: DelegatecallReceiverCaller{contract: contract}, DelegatecallReceiverTransactor: DelegatecallReceiverTransactor{contract: contract}, DelegatecallReceiverFilterer: DelegatecallReceiverFilterer{contract: contract}}, nil -} - -// DelegatecallReceiver is an auto generated Go binding around an Ethereum contract. -type DelegatecallReceiver struct { - DelegatecallReceiverCaller // Read-only binding to the contract - DelegatecallReceiverTransactor // Write-only binding to the contract - DelegatecallReceiverFilterer // Log filterer for contract events -} - -// DelegatecallReceiverCaller is an auto generated read-only Go binding around an Ethereum contract. -type DelegatecallReceiverCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallReceiverTransactor is an auto generated write-only Go binding around an Ethereum contract. -type DelegatecallReceiverTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallReceiverFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type DelegatecallReceiverFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallReceiverSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type DelegatecallReceiverSession struct { - Contract *DelegatecallReceiver // 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 -} - -// DelegatecallReceiverCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type DelegatecallReceiverCallerSession struct { - Contract *DelegatecallReceiverCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// DelegatecallReceiverTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type DelegatecallReceiverTransactorSession struct { - Contract *DelegatecallReceiverTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// DelegatecallReceiverRaw is an auto generated low-level Go binding around an Ethereum contract. -type DelegatecallReceiverRaw struct { - Contract *DelegatecallReceiver // Generic contract binding to access the raw methods on -} - -// DelegatecallReceiverCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type DelegatecallReceiverCallerRaw struct { - Contract *DelegatecallReceiverCaller // Generic read-only contract binding to access the raw methods on -} - -// DelegatecallReceiverTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type DelegatecallReceiverTransactorRaw struct { - Contract *DelegatecallReceiverTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewDelegatecallReceiver creates a new instance of DelegatecallReceiver, bound to a specific deployed contract. -func NewDelegatecallReceiver(address common.Address, backend bind.ContractBackend) (*DelegatecallReceiver, error) { - contract, err := bindDelegatecallReceiver(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &DelegatecallReceiver{DelegatecallReceiverCaller: DelegatecallReceiverCaller{contract: contract}, DelegatecallReceiverTransactor: DelegatecallReceiverTransactor{contract: contract}, DelegatecallReceiverFilterer: DelegatecallReceiverFilterer{contract: contract}}, nil -} - -// NewDelegatecallReceiverCaller creates a new read-only instance of DelegatecallReceiver, bound to a specific deployed contract. -func NewDelegatecallReceiverCaller(address common.Address, caller bind.ContractCaller) (*DelegatecallReceiverCaller, error) { - contract, err := bindDelegatecallReceiver(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &DelegatecallReceiverCaller{contract: contract}, nil -} - -// NewDelegatecallReceiverTransactor creates a new write-only instance of DelegatecallReceiver, bound to a specific deployed contract. -func NewDelegatecallReceiverTransactor(address common.Address, transactor bind.ContractTransactor) (*DelegatecallReceiverTransactor, error) { - contract, err := bindDelegatecallReceiver(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &DelegatecallReceiverTransactor{contract: contract}, nil -} - -// NewDelegatecallReceiverFilterer creates a new log filterer instance of DelegatecallReceiver, bound to a specific deployed contract. -func NewDelegatecallReceiverFilterer(address common.Address, filterer bind.ContractFilterer) (*DelegatecallReceiverFilterer, error) { - contract, err := bindDelegatecallReceiver(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &DelegatecallReceiverFilterer{contract: contract}, nil -} - -// bindDelegatecallReceiver binds a generic wrapper to an already deployed contract. -func bindDelegatecallReceiver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DelegatecallReceiverABI)) - 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 (_DelegatecallReceiver *DelegatecallReceiverRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DelegatecallReceiver.Contract.DelegatecallReceiverCaller.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 (_DelegatecallReceiver *DelegatecallReceiverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DelegatecallReceiver.Contract.DelegatecallReceiverTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DelegatecallReceiver *DelegatecallReceiverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DelegatecallReceiver.Contract.DelegatecallReceiverTransactor.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 (_DelegatecallReceiver *DelegatecallReceiverCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DelegatecallReceiver.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 (_DelegatecallReceiver *DelegatecallReceiverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DelegatecallReceiver.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DelegatecallReceiver *DelegatecallReceiverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DelegatecallReceiver.Contract.contract.Transact(opts, method, params...) -} - -// Entrypoint is a free data retrieval call binding the contract method 0xa65d69d4. -// -// Solidity: function entrypoint() view returns() -func (_DelegatecallReceiver *DelegatecallReceiverCaller) Entrypoint(opts *bind.CallOpts) error { - var out []interface{} - err := _DelegatecallReceiver.contract.Call(opts, &out, "entrypoint") - - if err != nil { - return err - } - - return err - -} - -// Entrypoint is a free data retrieval call binding the contract method 0xa65d69d4. -// -// Solidity: function entrypoint() view returns() -func (_DelegatecallReceiver *DelegatecallReceiverSession) Entrypoint() error { - return _DelegatecallReceiver.Contract.Entrypoint(&_DelegatecallReceiver.CallOpts) -} - -// Entrypoint is a free data retrieval call binding the contract method 0xa65d69d4. -// -// Solidity: function entrypoint() view returns() -func (_DelegatecallReceiver *DelegatecallReceiverCallerSession) Entrypoint() error { - return _DelegatecallReceiver.Contract.Entrypoint(&_DelegatecallReceiver.CallOpts) -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallReceiver *DelegatecallReceiverCaller) ExpectedSender(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _DelegatecallReceiver.contract.Call(opts, &out, "expectedSender") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallReceiver *DelegatecallReceiverSession) ExpectedSender() (common.Address, error) { - return _DelegatecallReceiver.Contract.ExpectedSender(&_DelegatecallReceiver.CallOpts) -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallReceiver *DelegatecallReceiverCallerSession) ExpectedSender() (common.Address, error) { - return _DelegatecallReceiver.Contract.ExpectedSender(&_DelegatecallReceiver.CallOpts) -} diff --git a/test/contracts/bin/DelegatecallSender/DelegatecallSender.go b/test/contracts/bin/DelegatecallSender/DelegatecallSender.go deleted file mode 100644 index f0d7b8998a..0000000000 --- a/test/contracts/bin/DelegatecallSender/DelegatecallSender.go +++ /dev/null @@ -1,254 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package DelegatecallSender - -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 -) - -// DelegatecallSenderMetaData contains all meta data concerning the DelegatecallSender contract. -var DelegatecallSenderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"call\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"expectedSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610359806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631754dba51461003b578063f55332ab1461006a575b600080fd5b60005461004e906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b61007d6100783660046101b1565b61007f565b005b600080546001600160a01b0319163317815560408051600481526024810182526020810180516001600160e01b03166329975a7560e21b179052905182916001600160a01b038516916100d29190610211565b600060405180830381855af49150503d806000811461010d576040519150601f19603f3d011682016040523d82523d6000602084013e610112565b606091505b5091509150816101675760448151101561012b57600080fd5b600481019050808060200190518101906101459190610243565b60405162461bcd60e51b815260040161015e91906102f0565b60405180910390fd5b816101ac5760405162461bcd60e51b815260206004820152601560248201527419195b1959d85d19590818d85b1b0819985a5b1959605a1b604482015260640161015e565b505050565b6000602082840312156101c357600080fd5b81356001600160a01b03811681146101da57600080fd5b9392505050565b60005b838110156101fc5781810151838201526020016101e4565b8381111561020b576000848401525b50505050565b600082516102238184602087016101e1565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561025557600080fd5b815167ffffffffffffffff8082111561026d57600080fd5b818401915084601f83011261028157600080fd5b8151818111156102935761029361022d565b604051601f8201601f19908116603f011681019083821181831017156102bb576102bb61022d565b816040528281528760208487010111156102d457600080fd5b6102e58360208301602088016101e1565b979650505050505050565b602081526000825180602084015261030f8160408501602087016101e1565b601f01601f1916919091016040019291505056fea26469706673582212204f0f7adb219400c7c8870f1d43741cb5a4764fba74d7a50a050044ddda02166564736f6c634300080c0033", -} - -// DelegatecallSenderABI is the input ABI used to generate the binding from. -// Deprecated: Use DelegatecallSenderMetaData.ABI instead. -var DelegatecallSenderABI = DelegatecallSenderMetaData.ABI - -// DelegatecallSenderBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use DelegatecallSenderMetaData.Bin instead. -var DelegatecallSenderBin = DelegatecallSenderMetaData.Bin - -// DeployDelegatecallSender deploys a new Ethereum contract, binding an instance of DelegatecallSender to it. -func DeployDelegatecallSender(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DelegatecallSender, error) { - parsed, err := DelegatecallSenderMetaData.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(DelegatecallSenderBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &DelegatecallSender{DelegatecallSenderCaller: DelegatecallSenderCaller{contract: contract}, DelegatecallSenderTransactor: DelegatecallSenderTransactor{contract: contract}, DelegatecallSenderFilterer: DelegatecallSenderFilterer{contract: contract}}, nil -} - -// DelegatecallSender is an auto generated Go binding around an Ethereum contract. -type DelegatecallSender struct { - DelegatecallSenderCaller // Read-only binding to the contract - DelegatecallSenderTransactor // Write-only binding to the contract - DelegatecallSenderFilterer // Log filterer for contract events -} - -// DelegatecallSenderCaller is an auto generated read-only Go binding around an Ethereum contract. -type DelegatecallSenderCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallSenderTransactor is an auto generated write-only Go binding around an Ethereum contract. -type DelegatecallSenderTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallSenderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type DelegatecallSenderFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// DelegatecallSenderSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type DelegatecallSenderSession struct { - Contract *DelegatecallSender // 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 -} - -// DelegatecallSenderCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type DelegatecallSenderCallerSession struct { - Contract *DelegatecallSenderCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// DelegatecallSenderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type DelegatecallSenderTransactorSession struct { - Contract *DelegatecallSenderTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// DelegatecallSenderRaw is an auto generated low-level Go binding around an Ethereum contract. -type DelegatecallSenderRaw struct { - Contract *DelegatecallSender // Generic contract binding to access the raw methods on -} - -// DelegatecallSenderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type DelegatecallSenderCallerRaw struct { - Contract *DelegatecallSenderCaller // Generic read-only contract binding to access the raw methods on -} - -// DelegatecallSenderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type DelegatecallSenderTransactorRaw struct { - Contract *DelegatecallSenderTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewDelegatecallSender creates a new instance of DelegatecallSender, bound to a specific deployed contract. -func NewDelegatecallSender(address common.Address, backend bind.ContractBackend) (*DelegatecallSender, error) { - contract, err := bindDelegatecallSender(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &DelegatecallSender{DelegatecallSenderCaller: DelegatecallSenderCaller{contract: contract}, DelegatecallSenderTransactor: DelegatecallSenderTransactor{contract: contract}, DelegatecallSenderFilterer: DelegatecallSenderFilterer{contract: contract}}, nil -} - -// NewDelegatecallSenderCaller creates a new read-only instance of DelegatecallSender, bound to a specific deployed contract. -func NewDelegatecallSenderCaller(address common.Address, caller bind.ContractCaller) (*DelegatecallSenderCaller, error) { - contract, err := bindDelegatecallSender(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &DelegatecallSenderCaller{contract: contract}, nil -} - -// NewDelegatecallSenderTransactor creates a new write-only instance of DelegatecallSender, bound to a specific deployed contract. -func NewDelegatecallSenderTransactor(address common.Address, transactor bind.ContractTransactor) (*DelegatecallSenderTransactor, error) { - contract, err := bindDelegatecallSender(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &DelegatecallSenderTransactor{contract: contract}, nil -} - -// NewDelegatecallSenderFilterer creates a new log filterer instance of DelegatecallSender, bound to a specific deployed contract. -func NewDelegatecallSenderFilterer(address common.Address, filterer bind.ContractFilterer) (*DelegatecallSenderFilterer, error) { - contract, err := bindDelegatecallSender(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &DelegatecallSenderFilterer{contract: contract}, nil -} - -// bindDelegatecallSender binds a generic wrapper to an already deployed contract. -func bindDelegatecallSender(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DelegatecallSenderABI)) - 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 (_DelegatecallSender *DelegatecallSenderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DelegatecallSender.Contract.DelegatecallSenderCaller.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 (_DelegatecallSender *DelegatecallSenderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DelegatecallSender.Contract.DelegatecallSenderTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DelegatecallSender *DelegatecallSenderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DelegatecallSender.Contract.DelegatecallSenderTransactor.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 (_DelegatecallSender *DelegatecallSenderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _DelegatecallSender.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 (_DelegatecallSender *DelegatecallSenderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _DelegatecallSender.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_DelegatecallSender *DelegatecallSenderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _DelegatecallSender.Contract.contract.Transact(opts, method, params...) -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallSender *DelegatecallSenderCaller) ExpectedSender(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _DelegatecallSender.contract.Call(opts, &out, "expectedSender") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallSender *DelegatecallSenderSession) ExpectedSender() (common.Address, error) { - return _DelegatecallSender.Contract.ExpectedSender(&_DelegatecallSender.CallOpts) -} - -// ExpectedSender is a free data retrieval call binding the contract method 0x1754dba5. -// -// Solidity: function expectedSender() view returns(address) -func (_DelegatecallSender *DelegatecallSenderCallerSession) ExpectedSender() (common.Address, error) { - return _DelegatecallSender.Contract.ExpectedSender(&_DelegatecallSender.CallOpts) -} - -// Call is a paid mutator transaction binding the contract method 0xf55332ab. -// -// Solidity: function call(address target) returns() -func (_DelegatecallSender *DelegatecallSenderTransactor) Call(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) { - return _DelegatecallSender.contract.Transact(opts, "call", target) -} - -// Call is a paid mutator transaction binding the contract method 0xf55332ab. -// -// Solidity: function call(address target) returns() -func (_DelegatecallSender *DelegatecallSenderSession) Call(target common.Address) (*types.Transaction, error) { - return _DelegatecallSender.Contract.Call(&_DelegatecallSender.TransactOpts, target) -} - -// Call is a paid mutator transaction binding the contract method 0xf55332ab. -// -// Solidity: function call(address target) returns() -func (_DelegatecallSender *DelegatecallSenderTransactorSession) Call(target common.Address) (*types.Transaction, error) { - return _DelegatecallSender.Contract.Call(&_DelegatecallSender.TransactOpts, target) -} diff --git a/test/contracts/bin/Destruct/Destruct.go b/test/contracts/bin/Destruct/Destruct.go index b912808faa..ed6d1f33b2 100644 --- a/test/contracts/bin/Destruct/Destruct.go +++ b/test/contracts/bin/Destruct/Destruct.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // DestructMetaData contains all meta data concerning the Destruct contract. @@ -156,11 +157,11 @@ func NewDestructFilterer(address common.Address, filterer bind.ContractFilterer) // bindDestruct binds a generic wrapper to an already deployed contract. func bindDestruct(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DestructABI)) + parsed, err := DestructMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Double/Double.go b/test/contracts/bin/Double/Double.go index 29a2bba05b..14f4600493 100644 --- a/test/contracts/bin/Double/Double.go +++ b/test/contracts/bin/Double/Double.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // DoubleMetaData contains all meta data concerning the Double contract. @@ -156,11 +157,11 @@ func NewDoubleFilterer(address common.Address, filterer bind.ContractFilterer) ( // bindDouble binds a generic wrapper to an already deployed contract. func bindDouble(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(DoubleABI)) + parsed, err := DoubleMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/ERC20/ERC20.go b/test/contracts/bin/ERC20/ERC20.go index 7eb1885fca..8fd9211f89 100644 --- a/test/contracts/bin/ERC20/ERC20.go +++ b/test/contracts/bin/ERC20/ERC20.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // ERC20MetaData contains all meta data concerning the ERC20 contract. @@ -156,11 +157,11 @@ func NewERC20Filterer(address common.Address, filterer bind.ContractFilterer) (* // bindERC20 binds a generic wrapper to an already deployed contract. func bindERC20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ERC20ABI)) + parsed, err := ERC20MetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/EmitLog/EmitLog.go b/test/contracts/bin/EmitLog/EmitLog.go index b0205c7ef9..3d69ae43f8 100644 --- a/test/contracts/bin/EmitLog/EmitLog.go +++ b/test/contracts/bin/EmitLog/EmitLog.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // EmitLogMetaData contains all meta data concerning the EmitLog contract. @@ -156,11 +157,11 @@ func NewEmitLogFilterer(address common.Address, filterer bind.ContractFilterer) // bindEmitLog binds a generic wrapper to an already deployed contract. func bindEmitLog(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(EmitLogABI)) + parsed, err := EmitLogMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/EmitLog2/EmitLog2.go b/test/contracts/bin/EmitLog2/EmitLog2.go index d9c2f3d542..831f3b83ca 100644 --- a/test/contracts/bin/EmitLog2/EmitLog2.go +++ b/test/contracts/bin/EmitLog2/EmitLog2.go @@ -26,12 +26,13 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // EmitLog2MetaData contains all meta data concerning the EmitLog2 contract. var EmitLog2MetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[],\"name\":\"Log\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"LogA\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"a\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"b\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"d\",\"type\":\"uint256\"}],\"name\":\"LogABCD\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"emitLogs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610101806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80637966b4f614602d575b600080fd5b60336035565b005b6040517f5e7df75d54e493185612379c616118a4c9ac802de621b010c96f74d22df4b30a90600090a16040516001907f977224b24e70d33f3be87246a29c5636cfc8dd6853e175b54af01ff493ffac6290600090a26003600260017fe5562b12d9276c5c987df08afff7b1946f2d869236866ea2285c7e2e95685a64600460405160c191815260200190565b60405180910390a456fea2646970667358221220a898ac615afab4fe6bf2c6b3f55f66eff9c2a50b0605c64082f0020f9fb56a4464736f6c634300080c0033", + Bin: "0x608060405234801561001057600080fd5b50610106806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80637966b4f614602d575b600080fd5b60336035565b005b60206000a06040517f5e7df75d54e493185612379c616118a4c9ac802de621b010c96f74d22df4b30a90600090a16040516001907f977224b24e70d33f3be87246a29c5636cfc8dd6853e175b54af01ff493ffac6290600090a26003600260017fe5562b12d9276c5c987df08afff7b1946f2d869236866ea2285c7e2e95685a64600460405160c691815260200190565b60405180910390a456fea2646970667358221220c82511092869da72fde6f1cec9478f4be47e0e13870c8d5af848ffddfeae937764736f6c634300080c0033", } // EmitLog2ABI is the input ABI used to generate the binding from. @@ -156,11 +157,11 @@ func NewEmitLog2Filterer(address common.Address, filterer bind.ContractFilterer) // bindEmitLog2 binds a generic wrapper to an already deployed contract. func bindEmitLog2(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(EmitLog2ABI)) + parsed, err := EmitLog2MetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/FailureTest/FailureTest.go b/test/contracts/bin/FailureTest/FailureTest.go index 87e3d801d8..fad845e530 100644 --- a/test/contracts/bin/FailureTest/FailureTest.go +++ b/test/contracts/bin/FailureTest/FailureTest.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // FailureTestMetaData contains all meta data concerning the FailureTest contract. @@ -156,11 +157,11 @@ func NewFailureTestFilterer(address common.Address, filterer bind.ContractFilter // bindFailureTest binds a generic wrapper to an already deployed contract. func bindFailureTest(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(FailureTestABI)) + parsed, err := FailureTestMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Interaction/Interaction.go b/test/contracts/bin/Interaction/Interaction.go index f815814044..3f13351015 100644 --- a/test/contracts/bin/Interaction/Interaction.go +++ b/test/contracts/bin/Interaction/Interaction.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // InteractionMetaData contains all meta data concerning the Interaction contract. @@ -156,11 +157,11 @@ func NewInteractionFilterer(address common.Address, filterer bind.ContractFilter // bindInteraction binds a generic wrapper to an already deployed contract. func bindInteraction(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(InteractionABI)) + parsed, err := InteractionMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Read/Read.go b/test/contracts/bin/Read/Read.go index a111117e29..7e32938d8f 100644 --- a/test/contracts/bin/Read/Read.go +++ b/test/contracts/bin/Read/Read.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // Readtoken is an auto generated low-level Go binding around an user-defined struct. @@ -163,11 +164,11 @@ func NewReadFilterer(address common.Address, filterer bind.ContractFilterer) (*R // bindRead binds a generic wrapper to an already deployed contract. func bindRead(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(ReadABI)) + parsed, err := ReadMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Revert/Revert.go b/test/contracts/bin/Revert/Revert.go index e85ea95ccd..aa0a3ac2c6 100644 --- a/test/contracts/bin/Revert/Revert.go +++ b/test/contracts/bin/Revert/Revert.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // RevertMetaData contains all meta data concerning the Revert contract. @@ -156,11 +157,11 @@ func NewRevertFilterer(address common.Address, filterer bind.ContractFilterer) ( // bindRevert binds a generic wrapper to an already deployed contract. func bindRevert(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(RevertABI)) + parsed, err := RevertMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Revert2/Revert2.go b/test/contracts/bin/Revert2/Revert2.go index 6bec99bdcc..90c5845ea0 100644 --- a/test/contracts/bin/Revert2/Revert2.go +++ b/test/contracts/bin/Revert2/Revert2.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // Revert2MetaData contains all meta data concerning the Revert2 contract. @@ -156,11 +157,11 @@ func NewRevert2Filterer(address common.Address, filterer bind.ContractFilterer) // bindRevert2 binds a generic wrapper to an already deployed contract. func bindRevert2(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(Revert2ABI)) + parsed, err := Revert2MetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/Storage/Storage.go b/test/contracts/bin/Storage/Storage.go index bd9d272fb3..3ce6af215a 100644 --- a/test/contracts/bin/Storage/Storage.go +++ b/test/contracts/bin/Storage/Storage.go @@ -26,12 +26,13 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // StorageMetaData contains all meta data concerning the Storage contract. var StorageMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"retrieve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"num\",\"type\":\"uint256\"}],\"name\":\"store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052348015600f57600080fd5b5060ac8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80632e64cec11460375780636057361d14604c575b600080fd5b60005460405190815260200160405180910390f35b605c6057366004605e565b600055565b005b600060208284031215606f57600080fd5b503591905056fea2646970667358221220c71ea90a41021b9719e82eff5992d4916d94a13b756c7f755b4a706562b1560564736f6c634300080c0033", + ABI: "[{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"retrieve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"num\",\"type\":\"uint256\"}],\"name\":\"store\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5060be8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80632e64cec11460415780636057361d14605657806386d1a69f146068575b600080fd5b60005460405190815260200160405180910390f35b606660613660046070565b600055565b005b606660008055565b600060208284031215608157600080fd5b503591905056fea26469706673582212202eca043b3baf32e10a795c1c4d247d829f1d205588205904dd65617589810c2c64736f6c634300080c0033", } // StorageABI is the input ABI used to generate the binding from. @@ -156,11 +157,11 @@ func NewStorageFilterer(address common.Address, filterer bind.ContractFilterer) // bindStorage binds a generic wrapper to an already deployed contract. func bindStorage(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(StorageABI)) + parsed, err := StorageMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and @@ -232,6 +233,27 @@ func (_Storage *StorageCallerSession) Retrieve() (*big.Int, error) { return _Storage.Contract.Retrieve(&_Storage.CallOpts) } +// Release is a paid mutator transaction binding the contract method 0x86d1a69f. +// +// Solidity: function release() returns() +func (_Storage *StorageTransactor) Release(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Storage.contract.Transact(opts, "release") +} + +// Release is a paid mutator transaction binding the contract method 0x86d1a69f. +// +// Solidity: function release() returns() +func (_Storage *StorageSession) Release() (*types.Transaction, error) { + return _Storage.Contract.Release(&_Storage.TransactOpts) +} + +// Release is a paid mutator transaction binding the contract method 0x86d1a69f. +// +// Solidity: function release() returns() +func (_Storage *StorageTransactorSession) Release() (*types.Transaction, error) { + return _Storage.Contract.Release(&_Storage.TransactOpts) +} + // Store is a paid mutator transaction binding the contract method 0x6057361d. // // Solidity: function store(uint256 num) returns() diff --git a/test/contracts/bin/StorageOnDeploy/StorageOnDeploy.go b/test/contracts/bin/StorageOnDeploy/StorageOnDeploy.go index 2f13a20e84..a004569f19 100644 --- a/test/contracts/bin/StorageOnDeploy/StorageOnDeploy.go +++ b/test/contracts/bin/StorageOnDeploy/StorageOnDeploy.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // StorageOnDeployMetaData contains all meta data concerning the StorageOnDeploy contract. @@ -156,11 +157,11 @@ func NewStorageOnDeployFilterer(address common.Address, filterer bind.ContractFi // bindStorageOnDeploy binds a generic wrapper to an already deployed contract. func bindStorageOnDeploy(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(StorageOnDeployABI)) + parsed, err := StorageOnDeployMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/WETH/WETH.go b/test/contracts/bin/WETH/WETH.go index 2914fd9869..a5af2b14c3 100644 --- a/test/contracts/bin/WETH/WETH.go +++ b/test/contracts/bin/WETH/WETH.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // WETHMetaData contains all meta data concerning the WETH contract. @@ -156,11 +157,11 @@ func NewWETHFilterer(address common.Address, filterer bind.ContractFilterer) (*W // bindWETH binds a generic wrapper to an already deployed contract. func bindWETH(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(WETHABI)) + parsed, err := WETHMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/core/UniswapV2ERC20/UniswapV2ERC20.go b/test/contracts/bin/uniswap/v2/core/UniswapV2ERC20/UniswapV2ERC20.go index d91ed92e6f..a765a96dec 100644 --- a/test/contracts/bin/uniswap/v2/core/UniswapV2ERC20/UniswapV2ERC20.go +++ b/test/contracts/bin/uniswap/v2/core/UniswapV2ERC20/UniswapV2ERC20.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapV2ERC20MetaData contains all meta data concerning the UniswapV2ERC20 contract. @@ -156,11 +157,11 @@ func NewUniswapV2ERC20Filterer(address common.Address, filterer bind.ContractFil // bindUniswapV2ERC20 binds a generic wrapper to an already deployed contract. func bindUniswapV2ERC20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapV2ERC20ABI)) + parsed, err := UniswapV2ERC20MetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/core/UniswapV2Factory/UniswapV2Factory.go b/test/contracts/bin/uniswap/v2/core/UniswapV2Factory/UniswapV2Factory.go index 39657da334..851896a117 100644 --- a/test/contracts/bin/uniswap/v2/core/UniswapV2Factory/UniswapV2Factory.go +++ b/test/contracts/bin/uniswap/v2/core/UniswapV2Factory/UniswapV2Factory.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapV2FactoryMetaData contains all meta data concerning the UniswapV2Factory contract. @@ -156,11 +157,11 @@ func NewUniswapV2FactoryFilterer(address common.Address, filterer bind.ContractF // bindUniswapV2Factory binds a generic wrapper to an already deployed contract. func bindUniswapV2Factory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapV2FactoryABI)) + parsed, err := UniswapV2FactoryMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/core/UniswapV2Pair/UniswapV2Pair.go b/test/contracts/bin/uniswap/v2/core/UniswapV2Pair/UniswapV2Pair.go index db61c61bd1..20c53d676a 100644 --- a/test/contracts/bin/uniswap/v2/core/UniswapV2Pair/UniswapV2Pair.go +++ b/test/contracts/bin/uniswap/v2/core/UniswapV2Pair/UniswapV2Pair.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapV2PairMetaData contains all meta data concerning the UniswapV2Pair contract. @@ -156,11 +157,11 @@ func NewUniswapV2PairFilterer(address common.Address, filterer bind.ContractFilt // bindUniswapV2Pair binds a generic wrapper to an already deployed contract. func bindUniswapV2Pair(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapV2PairABI)) + parsed, err := UniswapV2PairMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall/UniswapInterfaceMulticall.go b/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall/UniswapInterfaceMulticall.go index 3955b7656b..b88d605f78 100644 --- a/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall/UniswapInterfaceMulticall.go +++ b/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall/UniswapInterfaceMulticall.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapInterfaceMulticallCall is an auto generated low-level Go binding around an user-defined struct. @@ -170,11 +171,11 @@ func NewUniswapInterfaceMulticallFilterer(address common.Address, filterer bind. // bindUniswapInterfaceMulticall binds a generic wrapper to an already deployed contract. func bindUniswapInterfaceMulticall(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapInterfaceMulticallABI)) + parsed, err := UniswapInterfaceMulticallMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/periphery/UniswapV2Migrator/UniswapV2Migrator.go b/test/contracts/bin/uniswap/v2/periphery/UniswapV2Migrator/UniswapV2Migrator.go index f79544cf17..b371fd8f6a 100644 --- a/test/contracts/bin/uniswap/v2/periphery/UniswapV2Migrator/UniswapV2Migrator.go +++ b/test/contracts/bin/uniswap/v2/periphery/UniswapV2Migrator/UniswapV2Migrator.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapV2MigratorMetaData contains all meta data concerning the UniswapV2Migrator contract. @@ -156,11 +157,11 @@ func NewUniswapV2MigratorFilterer(address common.Address, filterer bind.Contract // bindUniswapV2Migrator binds a generic wrapper to an already deployed contract. func bindUniswapV2Migrator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapV2MigratorABI)) + parsed, err := UniswapV2MigratorMetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02/UniswapV2Router02.go b/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02/UniswapV2Router02.go index 5abb31a6ce..1a48a8b7a2 100644 --- a/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02/UniswapV2Router02.go +++ b/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02/UniswapV2Router02.go @@ -26,6 +26,7 @@ var ( _ = common.Big1 _ = types.BloomLookup _ = event.NewSubscription + _ = abi.ConvertType ) // UniswapV2Router02MetaData contains all meta data concerning the UniswapV2Router02 contract. @@ -156,11 +157,11 @@ func NewUniswapV2Router02Filterer(address common.Address, filterer bind.Contract // bindUniswapV2Router02 binds a generic wrapper to an already deployed contract. func bindUniswapV2Router02(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(UniswapV2Router02ABI)) + parsed, err := UniswapV2Router02MetaData.GetAbi() if err != nil { return nil, err } - return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } // Call invokes the (constant) contract method with params as input values and diff --git a/test/contracts/compiled/ERC20Token/ERC20Token.abi b/test/contracts/compiled/ERC20Token/ERC20Token.abi new file mode 100644 index 0000000000..e9cf331c73 --- /dev/null +++ b/test/contracts/compiled/ERC20Token/ERC20Token.abi @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"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":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/test/contracts/compiled/ERC20Token/ERC20Token.bin b/test/contracts/compiled/ERC20Token/ERC20Token.bin new file mode 100644 index 0000000000..d95a0a5999 --- /dev/null +++ b/test/contracts/compiled/ERC20Token/ERC20Token.bin @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b50604080518082018252601081526f22a9219918102a32b9ba102a37b5b2b760811b6020808301918252835180850190945260048452630545432360e41b9084015281519192916200006691600391620001d5565b5080516200007c906004906020840190620001d5565b5050506200009962000093620000b960201b60201c565b620000bd565b6b033b2e3c9fd0803ce8000000620000b233826200010f565b50620002df565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166200016a5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200017e91906200027b565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b828054620001e390620002a2565b90600052602060002090601f01602090048101928262000207576000855562000252565b82601f106200022257805160ff191683800117855562000252565b8280016001018555821562000252579182015b828111156200025257825182559160200191906001019062000235565b506200026092915062000264565b5090565b5b8082111562000260576000815560010162000265565b600082198211156200029d57634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680620002b757607f821691505b60208210811415620002d957634e487b7160e01b600052602260045260246000fd5b50919050565b610b0280620002ef6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a611610097578063a457c2d711610066578063a457c2d7146101eb578063a9059cbb146101fe578063dd62ed3e14610211578063f2fde38b1461022457600080fd5b8063715018a6146101ab5780637c4ca9cc146101b55780638da5cb5b146101c857806395d89b41146101e357600080fd5b806323b872dd116100d357806323b872dd1461014d578063313ce56714610160578063395093511461016f57806370a082311461018257600080fd5b806306fdde03146100fa578063095ea7b31461011857806318160ddd1461013b575b600080fd5b610102610237565b60405161010f9190610a16565b60405180910390f35b61012b6101263660046109ec565b6102c9565b604051901515815260200161010f565b6002545b60405190815260200161010f565b61012b61015b3660046109b0565b6102e1565b6040516012815260200161010f565b61012b61017d3660046109ec565b610305565b61013f61019036600461095b565b6001600160a01b031660009081526020819052604090205490565b6101b3610327565b005b6101b36101c33660046109ec565b61033b565b6005546040516001600160a01b03909116815260200161010f565b610102610351565b61012b6101f93660046109ec565b610360565b61012b61020c3660046109ec565b6103e0565b61013f61021f36600461097d565b6103ee565b6101b361023236600461095b565b610419565b60606003805461024690610a91565b80601f016020809104026020016040519081016040528092919081815260200182805461027290610a91565b80156102bf5780601f10610294576101008083540402835291602001916102bf565b820191906000526020600020905b8154815290600101906020018083116102a257829003601f168201915b5050505050905090565b6000336102d7818585610492565b5060019392505050565b6000336102ef8582856105b6565b6102fa858585610630565b506001949350505050565b6000336102d781858561031883836103ee565b6103229190610a6b565b610492565b61032f6107d4565b610339600061082e565b565b6103436107d4565b61034d8282610880565b5050565b60606004805461024690610a91565b6000338161036e82866103ee565b9050838110156103d35760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102fa8286868403610492565b6000336102d7818585610630565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6104216107d4565b6001600160a01b0381166104865760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103ca565b61048f8161082e565b50565b6001600160a01b0383166104f45760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103ca565b6001600160a01b0382166105555760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103ca565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006105c284846103ee565b9050600019811461062a578181101561061d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103ca565b61062a8484848403610492565b50505050565b6001600160a01b0383166106945760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103ca565b6001600160a01b0382166106f65760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103ca565b6001600160a01b0383166000908152602081905260409020548181101561076e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103ca565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a361062a565b6005546001600160a01b031633146103395760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103ca565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0382166108d65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103ca565b80600260008282546108e89190610a6b565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b80356001600160a01b038116811461095657600080fd5b919050565b60006020828403121561096d57600080fd5b6109768261093f565b9392505050565b6000806040838503121561099057600080fd5b6109998361093f565b91506109a76020840161093f565b90509250929050565b6000806000606084860312156109c557600080fd5b6109ce8461093f565b92506109dc6020850161093f565b9150604084013590509250925092565b600080604083850312156109ff57600080fd5b610a088361093f565b946020939093013593505050565b600060208083528351808285015260005b81811015610a4357858101830151858201604001528201610a27565b81811115610a55576000604083870101525b50601f01601f1916929092016040019392505050565b60008219821115610a8c57634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680610aa557607f821691505b60208210811415610ac657634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212209c7796851cb07f6ad8c6019fdbff6107a42a252cbc5120a345620ac4ffb1619664736f6c63430008070033 \ No newline at end of file diff --git a/test/contracts/compiled/MultiSigWallet/MultiSigWallet.abi b/test/contracts/compiled/MultiSigWallet/MultiSigWallet.abi new file mode 100644 index 0000000000..a06b8d0582 --- /dev/null +++ b/test/contracts/compiled/MultiSigWallet/MultiSigWallet.abi @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"}],"name":"ConfirmTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"}],"name":"ExecuteTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"}],"name":"RevokeConfirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"txIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"SubmitTransaction","type":"event"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"confirmTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"executeTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getApproveData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"getDecreaseAllowanceData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"getIncreaseAllowanceData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getOwners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"getTransaction","outputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bool","name":"executed","type":"bool"},{"internalType":"uint256","name":"numConfirmations","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransactionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getTransferData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getTransferFromData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"getTransferOwnershipData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"isConfirmed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numConfirmationsRequired","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_txIndex","type":"uint256"}],"name":"revokeConfirmation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"submitTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/test/contracts/compiled/MultiSigWallet/MultiSigWallet.bin b/test/contracts/compiled/MultiSigWallet/MultiSigWallet.bin new file mode 100644 index 0000000000..aafaeccd57 --- /dev/null +++ b/test/contracts/compiled/MultiSigWallet/MultiSigWallet.bin @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b5060405162001610380380620016108339810160408190526200003491620001f2565b600160005580516200007f5760405162461bcd60e51b815260206004820152600f60248201526e1bdddb995c9cc81c995c5d5a5c9959608a1b60448201526064015b60405180910390fd5b60005b8151811015620001cd576000828281518110620000a357620000a3620002cb565b6020026020010151905060006001600160a01b0316816001600160a01b03161415620001025760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b21037bbb732b960991b604482015260640162000076565b6001600160a01b03811660009081526004602052604090205460ff1615620001605760405162461bcd60e51b815260206004820152601060248201526f6f776e6572206e6f7420756e6971756560801b604482015260640162000076565b6001600160a01b03166000818152600460205260408120805460ff1916600190811790915580548082018255918190527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690910180546001600160a01b0319169092179091550162000082565b5050620002f7565b80516001600160a01b0381168114620001ed57600080fd5b919050565b600060208083850312156200020657600080fd5b82516001600160401b03808211156200021e57600080fd5b818501915085601f8301126200023357600080fd5b815181811115620002485762000248620002e1565b8060051b604051601f19603f83011681018181108582111715620002705762000270620002e1565b604052828152858101935084860182860187018a10156200029057600080fd5b600095505b83861015620002be57620002a981620001d5565b85526001959095019493860193860162000295565b5098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61130980620003076000396000f3fe6080604052600436106100f75760003560e01c806380f59a651161008a578063c568201f11610059578063c568201f1461049e578063c64274741461050a578063d0549b851461052a578063ee22610b1461053f57600080fd5b806380f59a65146103b5578063a0e67e2b146103f0578063ae36292814610412578063c01a8c841461047e57600080fd5b80632f54bf6e116100c65780632f54bf6e1461026c57806333ea3dc8146102ac57806346a898ef146102dd57806374108dbe1461034057600080fd5b80630bab9b0c1461013d5780631d5f8306146101bf57806320ea8d861461022b5780632e7700f01461024d57600080fd5b36610138576040805134815247602082015233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2005b600080fd5b34801561014957600080fd5b506101a9610158366004610ecd565b6040516001600160a01b03831660248201526044810182905260609060640160408051601f198184030181529190526020810180516001600160e01b031663095ea7b360e01b179052905092915050565b6040516101b69190611178565b60405180910390f35b3480156101cb57600080fd5b506101a96101da366004610ecd565b6040516001600160a01b03831660248201526044810182905260609060640160408051601f198184030181529190526020810180516001600160e01b031663a9059cbb60e01b179052905092915050565b34801561023757600080fd5b5061024b610246366004610fc2565b61055f565b005b34801561025957600080fd5b506002545b6040519081526020016101b6565b34801561027857600080fd5b5061029c610287366004610e6f565b60046020526000908152604090205460ff1681565b60405190151581526020016101b6565b3480156102b857600080fd5b506102cc6102c7366004610fc2565b6106ea565b6040516101b69594939291906110f0565b3480156102e957600080fd5b506101a96102f8366004610e6f565b6040516001600160a01b038216602482015260609060440160408051601f198184030181529190526020810180516001600160e01b031663f2fde38b60e01b17905292915050565b34801561034c57600080fd5b506101a961035b366004610e91565b6040516001600160a01b038085166024830152831660448201526064810182905260609060840160408051601f198184030181529190526020810180516001600160e01b03166323b872dd60e01b17905290509392505050565b3480156103c157600080fd5b5061029c6103d0366004610fdb565b600360209081526000928352604080842090915290825290205460ff1681565b3480156103fc57600080fd5b506104056107e5565b6040516101b6919061112b565b34801561041e57600080fd5b506101a961042d366004610ecd565b6040516001600160a01b03831660248201526044810182905260609060640160408051601f198184030181529190526020810180516001600160e01b0316633950935160e01b179052905092915050565b34801561048a57600080fd5b5061024b610499366004610fc2565b610847565b3480156104aa57600080fd5b506101a96104b9366004610ecd565b6040516001600160a01b03831660248201526044810182905260609060640160408051601f198184030181529190526020810180516001600160e01b031663a457c2d760e01b179052905092915050565b34801561051657600080fd5b5061024b610525366004610ef7565b6109d5565b34801561053657600080fd5b5061025e600381565b34801561054b57600080fd5b5061024b61055a366004610fc2565b610b5c565b3360009081526004602052604090205460ff166105975760405162461bcd60e51b815260040161058e906111e3565b60405180910390fd5b600254819081106105ba5760405162461bcd60e51b815260040161058e9061118b565b81600281815481106105ce576105ce6112a7565b600091825260209091206003600590920201015460ff16156106025760405162461bcd60e51b815260040161058e906111b6565b600060028481548110610617576106176112a7565b600091825260208083208784526003825260408085203386529092529220546005909102909101915060ff166106825760405162461bcd60e51b815260206004820152601060248201526f1d1e081b9bdd0818dbdb999a5c9b595960821b604482015260640161058e565b6001816004016000828254610697919061123f565b90915550506000848152600360209081526040808320338085529252808320805460ff191690555186927ff0dca620e2e81f7841d07bcc105e1704fb01475b278a9d4c236e1c62945edd5591a350505050565b6000806060600080600060028781548110610707576107076112a7565b6000918252602090912060059091020180546001820154600383015460048401546002850180549596506001600160a01b039094169492939260ff90921691839061075190611256565b80601f016020809104026020016040519081016040528092919081815260200182805461077d90611256565b80156107ca5780601f1061079f576101008083540402835291602001916107ca565b820191906000526020600020905b8154815290600101906020018083116107ad57829003601f168201915b50505050509250955095509550955095505091939590929450565b6060600180548060200260200160405190810160405280929190818152602001828054801561083d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161081f575b5050505050905090565b3360009081526004602052604090205460ff166108765760405162461bcd60e51b815260040161058e906111e3565b600254819081106108995760405162461bcd60e51b815260040161058e9061118b565b81600281815481106108ad576108ad6112a7565b600091825260209091206003600590920201015460ff16156108e15760405162461bcd60e51b815260040161058e906111b6565b6000838152600360209081526040808320338452909152902054839060ff16156109445760405162461bcd60e51b81526020600482015260146024820152731d1e08185b1c9958591e4818dbdb999a5c9b595960621b604482015260640161058e565b600060028581548110610959576109596112a7565b90600052602060002090600502019050600181600401600082825461097e9190611227565b90915550506000858152600360209081526040808320338085529252808320805460ff191660011790555187927f5cbe105e36805f7820e291f799d5794ff948af2a5f664e580382defb6339004191a35050505050565b3360009081526004602052604090205460ff16610a045760405162461bcd60e51b815260040161058e906111e3565b600280546040805160a0810182526001600160a01b0387811682526020808301888152938301878152600060608501819052608085018190526001870188559690965282517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace6005870290810180546001600160a01b0319169290941691909117835593517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf85015594518051949592949193610ae8937f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad090910192910190610dba565b50606082015160038201805460ff19169115159190911790556080909101516004909101556040516001600160a01b03851690829033907fd5a05bf70715ad82a09a756320284a1b54c9ff74cd0f8cce6219e79b563fe59d90610b4e9088908890611206565b60405180910390a450505050565b3360009081526004602052604090205460ff16610b8b5760405162461bcd60e51b815260040161058e906111e3565b60025481908110610bae5760405162461bcd60e51b815260040161058e9061118b565b8160028181548110610bc257610bc26112a7565b600091825260209091206003600590920201015460ff1615610bf65760405162461bcd60e51b815260040161058e906111b6565b610bfe610d60565b600060028481548110610c1357610c136112a7565b90600052602060002090600502019050600381600401541015610c6c5760405162461bcd60e51b81526020600482015260116024820152700c6c2dcdcdee840caf0cac6eae8ca40e8f607b1b604482015260640161058e565b60038101805460ff191660019081179091558154908201546040516000926001600160a01b03169190610ca3906002860190611054565b60006040518083038185875af1925050503d8060008114610ce0576040519150601f19603f3d011682016040523d82523d6000602084013e610ce5565b606091505b5050905080610d225760405162461bcd60e51b81526020600482015260096024820152681d1e0819985a5b195960ba1b604482015260640161058e565b604051859033907f5445f318f4f5fcfb66592e68e0cc5822aa15664039bd5f0ffde24c5a8142b1ac90600090a35050610d5b6001600055565b505050565b60026000541415610db35760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161058e565b6002600055565b828054610dc690611256565b90600052602060002090601f016020900481019282610de85760008555610e2e565b82601f10610e0157805160ff1916838001178555610e2e565b82800160010185558215610e2e579182015b82811115610e2e578251825591602001919060010190610e13565b50610e3a929150610e3e565b5090565b5b80821115610e3a5760008155600101610e3f565b80356001600160a01b0381168114610e6a57600080fd5b919050565b600060208284031215610e8157600080fd5b610e8a82610e53565b9392505050565b600080600060608486031215610ea657600080fd5b610eaf84610e53565b9250610ebd60208501610e53565b9150604084013590509250925092565b60008060408385031215610ee057600080fd5b610ee983610e53565b946020939093013593505050565b600080600060608486031215610f0c57600080fd5b610f1584610e53565b925060208401359150604084013567ffffffffffffffff80821115610f3957600080fd5b818601915086601f830112610f4d57600080fd5b813581811115610f5f57610f5f6112bd565b604051601f8201601f19908116603f01168101908382118183101715610f8757610f876112bd565b81604052828152896020848701011115610fa057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600060208284031215610fd457600080fd5b5035919050565b60008060408385031215610fee57600080fd5b82359150610ffe60208401610e53565b90509250929050565b6000815180845260005b8181101561102d57602081850181015186830182015201611011565b8181111561103f576000602083870101525b50601f01601f19169290920160200192915050565b600080835481600182811c91508083168061107057607f831692505b602080841082141561109057634e487b7160e01b86526022600452602486fd5b8180156110a457600181146110b5576110e2565b60ff198616895284890196506110e2565b60008a81526020902060005b868110156110da5781548b8201529085019083016110c1565b505084890196505b509498975050505050505050565b60018060a01b038616815284602082015260a06040820152600061111760a0830186611007565b931515606083015250608001529392505050565b6020808252825182820181905260009190848201906040850190845b8181101561116c5783516001600160a01b031683529284019291840191600101611147565b50909695505050505050565b602081526000610e8a6020830184611007565b6020808252601190820152701d1e08191bd95cc81b9bdd08195e1a5cdd607a1b604082015260600190565b6020808252601390820152721d1e08185b1c9958591e48195e1958dd5d1959606a1b604082015260600190565b6020808252600990820152683737ba1037bbb732b960b91b604082015260600190565b82815260406020820152600061121f6040830184611007565b949350505050565b6000821982111561123a5761123a611291565b500190565b60008282101561125157611251611291565b500390565b600181811c9082168061126a57607f821691505b6020821081141561128b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220412f9a2745e636812dc9e6207caccf42115ae337fa27c64cb7962e553984b50864736f6c63430008070033 \ No newline at end of file diff --git a/test/dbutils/dbutils.go b/test/dbutils/dbutils.go index c1fa6ba5d6..2db5b20145 100644 --- a/test/dbutils/dbutils.go +++ b/test/dbutils/dbutils.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/test/testutils" ) @@ -19,15 +20,10 @@ func InitOrResetPool(cfg db.Config) error { return initOrReset(cfg, "zkevm-pool-db") } -// InitOrResetRPC will initializes the RPC db running the migrations or -// will reset all the known data and rerun the migrations -func InitOrResetRPC(cfg db.Config) error { - return initOrReset(cfg, "zkevm-rpc-db") -} - // initOrReset will initializes the db running the migrations or -// will reset all the known data and rerun the migrations +// will reset all the known data and return the migrations func initOrReset(cfg db.Config, name string) error { + log.Infof("running migrations for %v", name) // connect to database dbPool, err := db.NewSQLDB(cfg) if err != nil { @@ -52,9 +48,9 @@ func NewPoolConfigFromEnv() db.Config { return newConfigFromEnv("pool", "5433") } -// NewRPCConfigFromEnv return a config for RPC db -func NewRPCConfigFromEnv() db.Config { - return newConfigFromEnv("rpc", "5434") +// NewEventConfigFromEnv return a config for event db +func NewEventConfigFromEnv() db.Config { + return newConfigFromEnv("event", "5435") } // newConfigFromEnv creates config from standard postgres environment variables, @@ -68,7 +64,7 @@ func newConfigFromEnv(prefix, port string) db.Config { Name: testutils.GetEnv("PGDATABASE", fmt.Sprintf("%v_db", prefix)), Host: testutils.GetEnv("PGHOST", "localhost"), Port: testutils.GetEnv("PGPORT", port), - EnableLog: true, + EnableLog: false, MaxConns: maxDBPoolConns, } } diff --git a/test/docker-compose.yml b/test/docker-compose.yml new file mode 100644 index 0000000000..2ee9daab9c --- /dev/null +++ b/test/docker-compose.yml @@ -0,0 +1,447 @@ +version: "3.5" +networks: + default: + name: zkevm + +services: + grafana: + container_name: grafana + image: grafana/grafana-oss + volumes: + - ./config/grafana/datasources.yml:/etc/grafana/provisioning/datasources/default.yml:ro + - ./config/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/default.yml:ro + - ./config/grafana/dashboard-dockers.json:/etc/grafana/provisioning/dashboards/dashboard-dockers.json:ro + - ./config/grafana/dashboard-node.json:/etc/grafana/provisioning/dashboards/dashboard-node.json:ro + environment: + - GF_SECURITY_ADMIN_USER=zkevm + - GF_SECURITY_ADMIN_PASSWORD=zkevm + ports: + - 3000:3000 + depends_on: + - telegraf + + telegraf: + container_name: telegraf + image: telegraf + volumes: + - ./config/telegraf.conf:/etc/telegraf/telegraf.conf:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + user: telegraf:${DOCKERGID} + environment: + - POSTGRES_HOST=grafana-db + - POSTGRES_USER=user + - POSTGRES_PASSWORD=password + - POSTGRES_DB=grafana + depends_on: + - grafana-db + - zkevm-json-rpc + + grafana-db: + container_name: grafana-db + image: postgres + expose: + - 5432 + environment: + - POSTGRES_USER=user + - POSTGRES_PASSWORD=password + - POSTGRES_DB=grafana + + zkevm-sequencer: + container_name: zkevm-sequencer + image: zkevm-node + ports: + - 9092:9091 # needed if metrics enabled + - 6060:6060 + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + - ZKEVM_NODE_POOL_DB_HOST=zkevm-pool-db + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components sequencer" + + zkevm-sequence-sender: + container_name: zkevm-sequence-sender + image: zkevm-node + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + - ZKEVM_NODE_POOL_DB_HOST=zkevm-pool-db + - ZKEVM_NODE_SEQUENCER_SENDER_ADDRESS=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 + volumes: + - ./sequencer.keystore:/pk/sequencer.keystore + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components sequence-sender" + + zkevm-json-rpc: + container_name: zkevm-json-rpc + image: zkevm-node + ports: + - 8123:8123 + - 8133:8133 # needed if WebSockets enabled + - 9091:9091 # needed if metrics enabled + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + - ZKEVM_NODE_POOL_DB_HOST=zkevm-pool-db + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components rpc" + + zkevm-aggregator: + container_name: zkevm-aggregator + image: zkevm-node + ports: + - 50081:50081 + - 9093:9091 # needed if metrics enabled + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + - ZKEVM_NODE_AGGREGATOR_SENDER_ADDRESS=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components aggregator" + + zkevm-sync: + container_name: zkevm-sync + image: zkevm-node + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components synchronizer" + + zkevm-eth-tx-manager: + container_name: zkevm-eth-tx-manager + image: zkevm-node + ports: + - 9094:9091 # needed if metrics enabled + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + volumes: + - ./sequencer.keystore:/pk/sequencer.keystore + - ./aggregator.keystore:/pk/aggregator.keystore + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components eth-tx-manager" + + zkevm-l2gaspricer: + container_name: zkevm-l2gaspricer + image: zkevm-node + environment: + - ZKEVM_NODE_POOL_DB_HOST=zkevm-pool-db + volumes: + - ./test.keystore:/pk/keystore + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components l2gaspricer" + + zkevm-state-db: + container_name: zkevm-state-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5432:5432 + volumes: + - ../db/scripts/init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql + environment: + - POSTGRES_USER=state_user + - POSTGRES_PASSWORD=state_password + - POSTGRES_DB=state_db + command: + - "postgres" + - "-N" + - "500" + + zkevm-pool-db: + container_name: zkevm-pool-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5433:5432 + environment: + - POSTGRES_USER=pool_user + - POSTGRES_PASSWORD=pool_password + - POSTGRES_DB=pool_db + command: + - "postgres" + - "-N" + - "500" + + zkevm-event-db: + container_name: zkevm-event-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5435:5432 + volumes: + - ../db/scripts/init_event_db.sql:/docker-entrypoint-initdb.d/init.sql + environment: + - POSTGRES_USER=event_user + - POSTGRES_PASSWORD=event_password + - POSTGRES_DB=event_db + command: + - "postgres" + - "-N" + - "500" + + zkevm-explorer-l1: + container_name: zkevm-explorer-l1 + image: hermeznetwork/hermez-node-blockscout:latest + ports: + - 4000:4000 + environment: + - NETWORK=ETH + - SUBNETWORK=Local Ethereum + - COIN=ETH + - ETHEREUM_JSONRPC_VARIANT=geth + - ETHEREUM_JSONRPC_HTTP_URL=http://zkevm-mock-l1-network:8545 + - DATABASE_URL=postgres://l1_explorer_user:l1_explorer_password@zkevm-explorer-l1-db:5432/l1_explorer_db + - ECTO_USE_SSL=false + - MIX_ENV=prod + command: + - "/bin/sh" + - "-c" + - "mix do ecto.create, ecto.migrate; mix phx.server" + + zkevm-explorer-l1-db: + container_name: zkevm-explorer-l1-db + image: postgres + ports: + - 5435:5432 + environment: + - POSTGRES_USER=l1_explorer_user + - POSTGRES_PASSWORD=l1_explorer_password + - POSTGRES_DB=l1_explorer_db + command: + - "postgres" + - "-N" + - "500" + + zkevm-explorer-l2: + container_name: zkevm-explorer-l2 + image: hermeznetwork/hermez-node-blockscout:latest + ports: + - 4001:4000 + environment: + - NETWORK=POE + - SUBNETWORK=Polygon Hermez + - COIN=ETH + - ETHEREUM_JSONRPC_VARIANT=geth + - ETHEREUM_JSONRPC_HTTP_URL=http://zkevm-explorer-json-rpc:8124 + - DATABASE_URL=postgres://l2_explorer_user:l2_explorer_password@zkevm-explorer-l2-db:5432/l2_explorer_db + - ECTO_USE_SSL=false + - MIX_ENV=prod + - LOGO=/images/blockscout_logo.svg + - LOGO_FOOTER=/images/blockscout_logo.svg + command: + - "/bin/sh" + - "-c" + - "mix do ecto.create, ecto.migrate; mix phx.server" + + zkevm-explorer-json-rpc: + container_name: zkevm-explorer-json-rpc + image: zkevm-node + ports: + - 8124:8124 + - 8134:8134 # needed if WebSockets enabled + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + - ZKEVM_NODE_POOL_DB_HOST=zkevm-pool-db + - ZKEVM_NODE_RPC_PORT=8124 + - ZKEVM_NODE_RPC_WEBSOCKETS_PORT=8134 + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components rpc --http.api eth,net,debug,zkevm,txpool,web3" + + zkevm-explorer-l2-db: + container_name: zkevm-explorer-l2-db + image: postgres + ports: + - 5436:5432 + environment: + - POSTGRES_USER=l2_explorer_user + - POSTGRES_PASSWORD=l2_explorer_password + - POSTGRES_DB=l2_explorer_db + command: [ "postgres", "-N", "500" ] + + zkevm-mock-l1-network: + container_name: zkevm-mock-l1-network + image: hermeznetwork/geth-zkevm-contracts:v1.1.0-fork.4 + ports: + - 8545:8545 + - 8546:8546 + command: + - "--http" + - "--http.api" + - "admin,eth,debug,miner,net,txpool,personal,web3" + - "--http.addr" + - "0.0.0.0" + - "--http.corsdomain" + - "*" + - "--http.vhosts" + - "*" + - "--ws" + - "--ws.origins" + - "*" + - "--ws.addr" + - "0.0.0.0" + - "--dev" + - "--datadir" + - "/geth_data" + - "--syncmode" + - "full" + - "--rpc.allow-unprotected-txs" + + zkevm-prover: + container_name: zkevm-prover + image: hermeznetwork/zkevm-prover:v1.1.3-RC2-fork.4 + ports: + # - 50051:50051 # Prover + - 50052:50052 # Mock prover + - 50061:50061 # MT + - 50071:50071 # Executor + volumes: + - ./config/test.prover.config.json:/usr/src/app/config.json + command: > + zkProver -c /usr/src/app/config.json + + zkprover-mock: + container_name: zkprover-mock + image: hermeznetwork/zkprover-mock:latest + ports: + - 43061:43061 # MT + - 43071:43071 # Executor + volumes: + - ./vectors/src:/app/testvectors + command: > + /app/zkprover-mock server --statedb-port 43061 --executor-port 43071 --test-vector-path /app/testvectors + + zkevm-approve: + container_name: zkevm-approve + image: zkevm-node + environment: + - ZKEVM_NODE_STATEDB_HOST=zkevm-state-db + volumes: + - ./sequencer.keystore:/pk/keystore + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node approve --network custom --custom-network-file /app/genesis.json --key-store-path /pk/keystore --pw testonly --am 115792089237316195423570985008687907853269984665640564039457584007913129639935 -y --cfg /app/config.toml" + + zkevm-permissionless-db: + container_name: zkevm-permissionless-db + image: postgres + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5434:5432 + volumes: + - ../db/scripts/single_db_server.sql:/docker-entrypoint-initdb.d/init.sql + environment: + - POSTGRES_USER=test_user + - POSTGRES_PASSWORD=test_password + - POSTGRES_DB=test_db + command: + - "postgres" + - "-N" + - "500" + + zkevm-permissionless-node: + container_name: zkevm-permissionless-node + image: zkevm-node + ports: + - 8125:8125 + environment: + - ZKEVM_NODE_ISTRUSTEDSEQUENCER=false + - ZKEVM_NODE_STATEDB_USER=test_user + - ZKEVM_NODE_STATEDB_PASSWORD=test_password + - ZKEVM_NODE_STATEDB_NAME=state_db + - ZKEVM_NODE_STATEDB_HOST=zkevm-permissionless-db + - ZKEVM_NODE_POOL_DB_USER=test_user + - ZKEVM_NODE_POOL_DB_PASSWORD=test_password + - ZKEVM_NODE_POOL_DB_NAME=pool_db + - ZKEVM_NODE_POOL_DB_HOST=zkevm-permissionless-db + - ZKEVM_NODE_RPC_PORT=8125 + - ZKEVM_NODE_RPC_SEQUENCERNODEURI=http://zkevm-json-rpc:8123 + - ZKEVM_NODE_MTCLIENT_URI=zkevm-permissionless-prover:50061 + - ZKEVM_NODE_EXECUTOR_URI=zkevm-permissionless-prover:50071 + volumes: + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node run --network custom --custom-network-file /app/genesis.json --cfg /app/config.toml --components \"rpc,synchronizer\"" + + zkevm-permissionless-prover: + container_name: zkevm-permissionless-prover + image: hermeznetwork/zkevm-prover:v1.1.3-RC2-fork.4 + ports: + # - 50058:50058 # Prover + - 50059:50052 # Mock prover + - 50068:50061 # MT + - 50078:50071 # Executor + volumes: + - ./config/test.permissionless.prover.config.json:/usr/src/app/config.json + command: > + zkProver -c /usr/src/app/config.json + + zkevm-metrics: + image: prom/prometheus:v2.39.1 + container_name: zkevm-metrics + restart: unless-stopped + ports: + - 9090:9090 + command: + - --config.file=/etc/prometheus/prometheus.yml + - --web.enable-lifecycle + volumes: + - ../config/metrics/prometheus:/etc/prometheus diff --git a/test/e2e/broadcast_test.go b/test/e2e/broadcast_test.go deleted file mode 100644 index a8f9117d90..0000000000 --- a/test/e2e/broadcast_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package e2e - -import ( - "context" - "fmt" - "math/big" - "testing" - "time" - - "github.com/0xPolygonHermez/zkevm-node/db" - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast" - "github.com/0xPolygonHermez/zkevm-node/sequencer/broadcast/pb" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" - "github.com/0xPolygonHermez/zkevm-node/test/dbutils" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/types/known/emptypb" -) - -const ( - serverAddress = "localhost:61090" - totalBatches = 2 - totalTxsLastBatch = 5 - encodedFmt = "encoded-%d" - forcedBatchNumber = 18 -) - -var ( - ctx = context.Background() - stateDBCfg = dbutils.NewStateConfigFromEnv() - ger = common.HexToHash("deadbeef") - mainnetExitRoot = common.HexToHash("caffe") - rollupExitRoot = common.HexToHash("bead") -) - -func TestBroadcast(t *testing.T) { - initOrResetDB() - - if testing.Short() { - t.Skip() - } - - require.NoError(t, operations.StartComponent("broadcast")) - defer func() { - require.NoError(t, operations.StopComponent("broadcast")) - }() - st, err := initState() - require.NoError(t, err) - - require.NoError(t, populateDB(ctx, st)) - - client, conn, cancel := broadcast.NewClient(ctx, serverAddress) - defer func() { - cancel() - require.NoError(t, conn.Close()) - }() - - lastBatch, err := client.GetLastBatch(ctx, &emptypb.Empty{}) - require.NoError(t, err) - require.Equal(t, totalBatches, int(lastBatch.BatchNumber)) - - batch, err := client.GetBatch(ctx, &pb.GetBatchRequest{ - BatchNumber: uint64(totalBatches), - }) - require.NoError(t, err) - require.Equal(t, totalBatches, int(batch.BatchNumber)) - - require.Equal(t, totalTxsLastBatch, len(batch.Transactions)) - - for i, tx := range batch.Transactions { - require.Equal(t, fmt.Sprintf(encodedFmt, i+1), tx.Encoded) - } - require.EqualValues(t, forcedBatchNumber, batch.ForcedBatchNumber) - - require.Equal(t, mainnetExitRoot.String(), batch.MainnetExitRoot) - require.Equal(t, rollupExitRoot.String(), batch.RollupExitRoot) -} - -func initState() (*state.State, error) { - initOrResetDB() - sqlDB, err := db.NewSQLDB(stateDBCfg) - if err != nil { - return nil, err - } - stateDb := state.NewPostgresStorage(sqlDB) - executorClient, _, _ := executor.NewExecutorClient(ctx, executor.Config{URI: "127.0.0.1:50071"}) - mtDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, merkletree.Config{URI: "127.0.0.1:50061"}) - stateTree := merkletree.NewStateTree(mtDBClient) - return state.NewState(state.Config{}, stateDb, executorClient, stateTree), nil -} - -func populateDB(ctx context.Context, st *state.State) error { - const blockNumber = 1 - - var parentHash common.Hash - var l2Block types.Block - - const addBatch = "INSERT INTO state.batch (batch_num, global_exit_root, timestamp, coinbase, local_exit_root, state_root) VALUES ($1, $2, $3, $4, $5, $6)" - for i := 1; i <= totalBatches; i++ { - if _, err := st.PostgresStorage.Exec(ctx, addBatch, i, ger.String(), time.Now(), common.HexToAddress("").String(), common.Hash{}.String(), common.Hash{}.String()); err != nil { - return err - } - } - - for i := 1; i <= totalTxsLastBatch; i++ { - if i == 1 { - parentHash = state.ZeroHash - } else { - parentHash = l2Block.Hash() - } - - // Store L2 Genesis Block - header := new(types.Header) - header.Number = new(big.Int).SetUint64(uint64(i - 1)) - header.ParentHash = parentHash - l2Block := types.NewBlockWithHeader(header) - l2Block.ReceivedAt = time.Now() - - if err := st.PostgresStorage.AddL2Block(ctx, totalBatches, l2Block, []*types.Receipt{}, nil); err != nil { - return err - } - - const addTransaction = "INSERT INTO state.transaction (hash, encoded, l2_block_num) VALUES ($1, $2, $3)" - if _, err := st.PostgresStorage.Exec(ctx, addTransaction, fmt.Sprintf("hash-%d", i), fmt.Sprintf(encodedFmt, i), l2Block.Number().Uint64()); err != nil { - return err - } - } - - const addBlock = "INSERT INTO state.block (block_num, received_at, block_hash) VALUES ($1, $2, $3)" - if _, err := st.PostgresStorage.Exec(ctx, addBlock, blockNumber, time.Now(), ""); err != nil { - return err - } - - const addForcedBatch = "INSERT INTO state.forced_batch (forced_batch_num, global_exit_root, raw_txs_data, coinbase, timestamp, batch_num, block_num) VALUES ($1, $2, $3, $4, $5, $6, $7)" - if _, err := st.PostgresStorage.Exec(ctx, addForcedBatch, forcedBatchNumber, ger.String(), "", common.HexToAddress("").String(), time.Now(), totalBatches, blockNumber); err != nil { - return err - } - - const addExitRoots = "INSERT INTO state.exit_root (block_num, global_exit_root, mainnet_exit_root, rollup_exit_root, global_exit_root_num) VALUES ($1, $2, $3, $4, $5)" - _, err := st.PostgresStorage.Exec(ctx, addExitRoots, blockNumber, ger, mainnetExitRoot, rollupExitRoot, 1) - return err -} - -func initOrResetDB() { - if err := dbutils.InitOrResetState(stateDBCfg); err != nil { - panic(err) - } -} diff --git a/test/e2e/debug_calltracer_test.go b/test/e2e/debug_calltracer_test.go new file mode 100644 index 0000000000..063bfd2113 --- /dev/null +++ b/test/e2e/debug_calltracer_test.go @@ -0,0 +1,414 @@ +package e2e + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "strings" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestDebugTraceTransactionCallTracer(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + results := map[string]json.RawMessage{} + + type testCase struct { + name string + prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) + createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) + } + testCases := []testCase{ + // successful transactions + {name: "eth transfer", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment", createSignedTx: createScDeploySignedTx}, + {name: "sc call", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + {name: "create", prepare: prepareCreate, createSignedTx: createCreateSignedTx}, + {name: "create2", prepare: prepareCreate, createSignedTx: createCreate2SignedTx}, + {name: "call", prepare: prepareCalls, createSignedTx: createCallSignedTx}, + {name: "delegate call", prepare: prepareCalls, createSignedTx: createDelegateCallSignedTx}, + {name: "multi call", prepare: prepareCalls, createSignedTx: createMultiCallSignedTx}, + {name: "pre ecrecover 0", prepare: prepareCalls, createSignedTx: createPreEcrecover0SignedTx}, + {name: "chain call", prepare: prepareChainCalls, createSignedTx: createChainCallSignedTx}, + + // failed transactions + {name: "sc deployment reverted", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + {name: "invalid static call less parameters", prepare: prepareCalls, createSignedTx: createInvalidStaticCallLessParametersSignedTx}, + {name: "invalid static call more parameters", prepare: prepareCalls, createSignedTx: createInvalidStaticCallMoreParametersSignedTx}, + {name: "invalid static call with inner call", prepare: prepareCalls, createSignedTx: createInvalidStaticCallWithInnerCallSignedTx}, + } + privateKey, err := crypto.GenerateKey() + require.NoError(t, err) + for _, network := range networks { + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) + require.NoError(t, err) + + ethereumClient := operations.MustGetClient(network.URL) + sourceAuth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + nonce, err := ethereumClient.NonceAt(ctx, sourceAuth.From, nil) + require.NoError(t, err) + + balance, err := ethereumClient.BalanceAt(ctx, sourceAuth.From, nil) + require.NoError(t, err) + + gasPrice, err := ethereumClient.SuggestGasPrice(ctx) + require.NoError(t, err) + + value := big.NewInt(0).Quo(balance, big.NewInt(2)) + + gas, err := ethereumClient.EstimateGas(ctx, ethereum.CallMsg{ + From: sourceAuth.From, + To: &auth.From, + GasPrice: gasPrice, + Value: value, + }) + require.NoError(t, err) + + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + To: &auth.From, + Nonce: nonce, + GasPrice: gasPrice, + Value: value, + Gas: gas, + }) + + signedTx, err := sourceAuth.Signer(sourceAuth.From, tx) + require.NoError(t, err) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + log.Debug("************************ ", tc.name, " ************************") + + for _, network := range networks { + log.Debug("------------------------ ", network.Name, " ------------------------") + ethereumClient := operations.MustGetClient(network.URL) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) + require.NoError(t, err) + + var customData map[string]interface{} + if tc.prepare != nil { + customData, err = tc.prepare(t, ctx, auth, ethereumClient) + require.NoError(t, err) + } + + signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) + require.NoError(t, err) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + log.Debugf("tx sent: %v", signedTx.Hash().String()) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { + require.NoError(t, err) + } + + debugOptions := map[string]interface{}{ + "tracer": "callTracer", + "tracerConfig": map[string]interface{}{ + "onlyTopCall": false, + "withLog": true, + }, + } + + response, err := client.JSONRPCCall(network.URL, "debug_traceTransaction", signedTx.Hash().String(), debugOptions) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + results[network.Name] = response.Result + log.Debug(string(response.Result)) + + saveTraceResultToFile(t, tc.name, network.Name, signedTx, response.Result, true) + } + + referenceValueMap := map[string]interface{}{} + err = json.Unmarshal(results[l1NetworkName], &referenceValueMap) + require.NoError(t, err) + + for networkName, result := range results { + if networkName == l1NetworkName { + continue + } + + resultMap := map[string]interface{}{} + err = json.Unmarshal(result, &resultMap) + require.NoError(t, err) + + compareCallFrame(t, referenceValueMap, resultMap, networkName) + } + }) + } +} + +func compareCallFrame(t *testing.T, referenceValueMap, resultMap map[string]interface{}, networkName string) { + require.Equal(t, referenceValueMap["from"], resultMap["from"], fmt.Sprintf("invalid `from` for network %s", networkName)) + require.Equal(t, referenceValueMap["input"], resultMap["input"], fmt.Sprintf("invalid `input` for network %s", networkName)) + require.Equal(t, referenceValueMap["output"], resultMap["output"], fmt.Sprintf("invalid `output` for network %s", networkName)) + require.Equal(t, referenceValueMap["value"], resultMap["value"], fmt.Sprintf("invalid `value` for network %s", networkName)) + require.Equal(t, referenceValueMap["type"], resultMap["type"], fmt.Sprintf("invalid `type` for network %s", networkName)) + require.Equal(t, referenceValueMap["error"], resultMap["error"], fmt.Sprintf("invalid `error` for network %s", networkName)) + require.Equal(t, referenceValueMap["revertReason"], resultMap["revertReason"], fmt.Sprintf("invalid `revertReason` for network %s", networkName)) + + referenceLogs, found := referenceValueMap["logs"].([]interface{}) + if found { + resultLogs := resultMap["logs"].([]interface{}) + require.Equal(t, len(referenceLogs), len(resultLogs), "logs size doesn't match") + for logIndex := range referenceLogs { + referenceLog := referenceLogs[logIndex].(map[string]interface{}) + resultLog := resultLogs[logIndex].(map[string]interface{}) + + require.Equal(t, referenceLog["data"], resultLog["data"], fmt.Sprintf("log index %v data doesn't match", logIndex)) + referenceTopics, found := referenceLog["topics"].([]interface{}) + if found { + resultTopics := resultLog["topics"].([]interface{}) + require.Equal(t, len(referenceTopics), len(resultTopics), "log index %v topics size doesn't match", logIndex) + for topicIndex := range referenceTopics { + require.Equal(t, referenceTopics[topicIndex], resultTopics[topicIndex], fmt.Sprintf("log index %v topic index %v doesn't match", logIndex, topicIndex)) + } + } + } + } + + referenceCalls, found := referenceValueMap["calls"].([]interface{}) + if found { + resultCalls := resultMap["calls"].([]interface{}) + require.Equal(t, len(referenceCalls), len(resultCalls), "logs size doesn't match") + for callIndex := range referenceCalls { + referenceCall := referenceCalls[callIndex].(map[string]interface{}) + resultCall := resultCalls[callIndex].(map[string]interface{}) + + compareCallFrame(t, referenceCall, resultCall, networkName) + } + } +} + +func TestDebugTraceBlockCallTracer(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + results := map[string]json.RawMessage{} + + type testCase struct { + name string + blockNumberOrHash string + prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) + createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) + } + testCases := []testCase{ + // successful transactions + // by block number + {name: "eth transfer by number", blockNumberOrHash: "number", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment by number", blockNumberOrHash: "number", createSignedTx: createScDeploySignedTx}, + {name: "sc call by number", blockNumberOrHash: "number", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer by number", blockNumberOrHash: "number", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + // by block hash + {name: "eth transfer by hash", blockNumberOrHash: "hash", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment by hash", blockNumberOrHash: "hash", createSignedTx: createScDeploySignedTx}, + {name: "sc call by hash", blockNumberOrHash: "hash", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer by hash", blockNumberOrHash: "hash", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + + // failed transactions + // by block number + {name: "sc deployment reverted by number", blockNumberOrHash: "number", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted by number", blockNumberOrHash: "number", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted by number", blockNumberOrHash: "number", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + // by block hash + {name: "sc deployment reverted by hash", blockNumberOrHash: "hash", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted by hash", blockNumberOrHash: "hash", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted by hash", blockNumberOrHash: "hash", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + log.Debug("************************ ", tc.name, " ************************") + + for _, network := range networks { + log.Debug("------------------------ ", network.Name, " ------------------------") + ethereumClient := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + var customData map[string]interface{} + if tc.prepare != nil { + customData, err = tc.prepare(t, ctx, auth, ethereumClient) + require.NoError(t, err) + } + + signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) + require.NoError(t, err) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + log.Debugf("tx sent: %v", signedTx.Hash().String()) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { + require.NoError(t, err) + } + + receipt, err := ethereumClient.TransactionReceipt(ctx, signedTx.Hash()) + require.NoError(t, err) + + debugOptions := map[string]interface{}{ + "tracer": "callTracer", + "tracerConfig": map[string]interface{}{ + "onlyTopCall": false, + "withLog": true, + }, + } + + var response types.Response + if tc.blockNumberOrHash == "number" { + response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByNumber", hex.EncodeBig(receipt.BlockNumber), debugOptions) + } else { + response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByHash", receipt.BlockHash.String(), debugOptions) + } + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + results[network.Name] = response.Result + } + + referenceTransactions := []interface{}{} + err = json.Unmarshal(results[l1NetworkName], &referenceTransactions) + require.NoError(t, err) + + for networkName, result := range results { + if networkName == l1NetworkName { + continue + } + + resultTransactions := []interface{}{} + err = json.Unmarshal(result, &resultTransactions) + require.NoError(t, err) + + for transactionIndex := range referenceTransactions { + referenceTransactionMap := referenceTransactions[transactionIndex].(map[string]interface{}) + resultTransactionMap := resultTransactions[transactionIndex].(map[string]interface{}) + + compareCallFrame(t, referenceTransactionMap, resultTransactionMap, networkName) + } + } + }) + } +} diff --git a/test/e2e/debug_shared.go b/test/e2e/debug_shared.go new file mode 100644 index 0000000000..55108da58a --- /dev/null +++ b/test/e2e/debug_shared.go @@ -0,0 +1,525 @@ +package e2e + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "os" + "strings" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Called" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Caller" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ChainCallLevel1" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ChainCallLevel2" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ChainCallLevel3" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ChainCallLevel4" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Counter" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Creates" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/EmitLog" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Revert2" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const fixedTxGasLimit uint64 = 100000 + +func createEthTransferSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + to := common.HexToAddress("0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98") + + gas, err := client.EstimateGas(ctx, ethereum.CallMsg{ + From: auth.From, + To: &to, + }) + require.NoError(t, err) + + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: nonce, + To: &to, + GasPrice: gasPrice, + Gas: gas, + }) + + return auth.Signer(auth.From, tx) +} + +func createScDeploySignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + scByteCode, err := testutils.ReadBytecode("Counter/Counter.bin") + require.NoError(t, err) + data := common.Hex2Bytes(scByteCode) + + gas, err := client.EstimateGas(ctx, ethereum.CallMsg{ + From: auth.From, + Data: data, + }) + require.NoError(t, err) + + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: gas, + Data: data, + }) + + return auth.Signer(auth.From, tx) +} + +func prepareScCall(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + _, tx, sc, err := EmitLog.DeployEmitLog(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + }, nil +} + +func createScCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*EmitLog.EmitLog) + + opts := *auth + opts.NoSend = true + + tx, err := sc.EmitLogs(&opts) + require.NoError(t, err) + + return tx, nil +} + +func prepareERC20Transfer(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + _, tx, sc, err := ERC20.DeployERC20(auth, client, "MyToken", "MT") + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + tx, err = sc.Mint(auth, big.NewInt(1000000000)) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + }, nil +} + +func createERC20TransferSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*ERC20.ERC20) + + opts := *auth + opts.NoSend = true + + to := common.HexToAddress("0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98") + + tx, err := sc.Transfer(&opts, to, big.NewInt(123456)) + require.NoError(t, err) + + return tx, nil +} + +func createScDeployRevertedSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + scByteCode, err := testutils.ReadBytecode("Revert/Revert.bin") + require.NoError(t, err) + data := common.Hex2Bytes(scByteCode) + + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: fixedTxGasLimit, + Data: data, + }) + + return auth.Signer(auth.From, tx) +} + +func prepareScCallReverted(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + _, tx, sc, err := Revert2.DeployRevert2(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + }, nil +} + +func createScCallRevertedSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Revert2.Revert2) + + opts := *auth + opts.NoSend = true + opts.GasLimit = fixedTxGasLimit + + tx, err := sc.GenerateError(&opts) + require.NoError(t, err) + + return tx, nil +} + +func prepareERC20TransferReverted(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + _, tx, sc, err := ERC20.DeployERC20(auth, client, "MyToken2", "MT2") + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + }, nil +} + +func createERC20TransferRevertedSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*ERC20.ERC20) + + opts := *auth + opts.NoSend = true + opts.GasLimit = fixedTxGasLimit + + to := common.HexToAddress("0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98") + + tx, err := sc.Transfer(&opts, to, big.NewInt(123456)) + require.NoError(t, err) + + return tx, nil +} + +func prepareCreate(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + _, tx, sc, err := Creates.DeployCreates(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + }, nil +} + +func createCreateSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Creates.Creates) + + opts := *auth + opts.NoSend = true + + byteCode := hex.DecodeBig(Counter.CounterBin).Bytes() + + tx, err := sc.OpCreate(&opts, byteCode, big.NewInt(0).SetInt64(int64(len(byteCode)))) + require.NoError(t, err) + + return tx, nil +} + +func createCreate2SignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Creates.Creates) + + opts := *auth + opts.NoSend = true + + byteCode := hex.DecodeBig(Counter.CounterBin).Bytes() + + tx, err := sc.OpCreate2(&opts, byteCode, big.NewInt(0).SetInt64(int64(len(byteCode)))) + require.NoError(t, err) + + return tx, nil +} + +func prepareCalls(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + scAddr, tx, _, err := Called.DeployCalled(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + _, tx, sc, err := Caller.DeployCaller(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + "calledAddress": scAddr, + }, nil +} + +func createCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.Call(&opts, calledAddress, big.NewInt(1984)) + require.NoError(t, err) + + return tx, nil +} + +func createDelegateCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.DelegateCall(&opts, calledAddress, big.NewInt(1984)) + require.NoError(t, err) + + return tx, nil +} + +func createMultiCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.MultiCall(&opts, calledAddress, big.NewInt(1984)) + require.NoError(t, err) + + return tx, nil +} + +func createInvalidStaticCallLessParametersSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.InvalidStaticCallLessParameters(&opts, calledAddress) + require.NoError(t, err) + + return tx, nil +} + +func createInvalidStaticCallMoreParametersSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.InvalidStaticCallMoreParameters(&opts, calledAddress) + require.NoError(t, err) + + return tx, nil +} + +func createInvalidStaticCallWithInnerCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + calledAddressInterface := customData["calledAddress"] + calledAddress := calledAddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.InvalidStaticCallWithInnerCall(&opts, calledAddress) + require.NoError(t, err) + + return tx, nil +} + +func createPreEcrecover0SignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*Caller.Caller) + + opts := *auth + opts.NoSend = true + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.PreEcrecover0(&opts) + require.NoError(t, err) + + return tx, nil +} + +func prepareChainCalls(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) { + scAddrLevel4, tx, _, err := ChainCallLevel4.DeployChainCallLevel4(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + scAddrLevel3, tx, _, err := ChainCallLevel3.DeployChainCallLevel3(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + scAddrLevel2, tx, _, err := ChainCallLevel2.DeployChainCallLevel2(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + _, tx, sc, err := ChainCallLevel1.DeployChainCallLevel1(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + return map[string]interface{}{ + "sc": sc, + "level2Address": scAddrLevel2, + "level3Address": scAddrLevel3, + "level4Address": scAddrLevel4, + }, nil +} + +func createChainCallSignedTx(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) { + scInterface := customData["sc"] + sc := scInterface.(*ChainCallLevel1.ChainCallLevel1) + + level2AddressInterface := customData["level2Address"] + level2Address := level2AddressInterface.(common.Address) + + level3AddressInterface := customData["level3Address"] + level3Address := level3AddressInterface.(common.Address) + + level4AddressInterface := customData["level4Address"] + level4Address := level4AddressInterface.(common.Address) + + opts := *auth + opts.NoSend = true + opts.Value = big.NewInt(2509) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + opts.GasPrice = gasPrice + opts.GasLimit = uint64(300000) + + tx, err := sc.Exec(&opts, level2Address, level3Address, level4Address) + require.NoError(t, err) + + return tx, nil +} + +func saveTraceResultToFile(t *testing.T, name, network string, signedTx *ethTypes.Transaction, trace json.RawMessage, skip bool) { + if skip { + return + } + const path = "/Users/thiago/github.com/0xPolygonHermez/zkevm-node/dist/%v.json" + sanitizedNetworkName := strings.ReplaceAll(name+network+"_", " ", "_") + filePath := fmt.Sprintf(path, sanitizedNetworkName) + b, _ := signedTx.MarshalBinary() + fileContent := struct { + Tx *ethTypes.Transaction + RLP string + Trace json.RawMessage + }{ + Tx: signedTx, + RLP: hex.EncodeToHex(b), + Trace: trace, + } + c, err := json.MarshalIndent(fileContent, "", " ") + require.NoError(t, err) + err = os.WriteFile(filePath, c, 0644) + require.NoError(t, err) +} diff --git a/test/e2e/debug_test.go b/test/e2e/debug_test.go new file mode 100644 index 0000000000..6e3022fee7 --- /dev/null +++ b/test/e2e/debug_test.go @@ -0,0 +1,666 @@ +package e2e + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "strings" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestDebugTraceTransactionNotFoundTx(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + for _, network := range networks { + log.Debugf(network.Name) + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: 10, + }) + + response, err := client.JSONRPCCall(network.URL, "debug_traceTransaction", tx.Hash().String()) + require.NoError(t, err) + require.Nil(t, response.Result) + require.NotNil(t, response.Error) + + require.Equal(t, -32000, response.Error.Code) + require.Equal(t, "transaction not found", response.Error.Message) + require.Nil(t, response.Error.Data) + } +} + +func TestDebugTraceBlockByNumberNotFoundTx(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + for _, network := range networks { + log.Debugf(network.Name) + + response, err := client.JSONRPCCall(network.URL, "debug_traceBlockByNumber", hex.EncodeBig(big.NewInt(999999999999))) + require.NoError(t, err) + require.Nil(t, response.Result) + require.NotNil(t, response.Error) + + require.Equal(t, -32000, response.Error.Code) + require.Equal(t, "block #999999999999 not found", response.Error.Message) + require.Nil(t, response.Error.Data) + } +} + +func TestDebugTraceBlockByHashNotFoundTx(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + for _, network := range networks { + log.Debugf(network.Name) + + response, err := client.JSONRPCCall(network.URL, "debug_traceBlockByHash", common.Hash{}.String()) + require.NoError(t, err) + require.Nil(t, response.Result) + require.NotNil(t, response.Error) + + require.Equal(t, -32000, response.Error.Code) + require.Equal(t, "block 0x0000000000000000000000000000000000000000000000000000000000000000 not found", response.Error.Message) + require.Nil(t, response.Error.Data) + } +} + +func TestDebugTraceTransaction(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + results := map[string]json.RawMessage{} + + type testCase struct { + name string + prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) + createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) + } + testCases := []testCase{ + // successful transactions + {name: "eth transfer", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment", createSignedTx: createScDeploySignedTx}, + {name: "sc call", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + {name: "create", prepare: prepareCreate, createSignedTx: createCreateSignedTx}, + {name: "create2", prepare: prepareCreate, createSignedTx: createCreate2SignedTx}, + {name: "call", prepare: prepareCalls, createSignedTx: createCallSignedTx}, + {name: "delegate call", prepare: prepareCalls, createSignedTx: createDelegateCallSignedTx}, + {name: "multi call", prepare: prepareCalls, createSignedTx: createMultiCallSignedTx}, + {name: "pre ecrecover 0", prepare: prepareCalls, createSignedTx: createPreEcrecover0SignedTx}, + {name: "chain call", prepare: prepareChainCalls, createSignedTx: createChainCallSignedTx}, + + // failed transactions + {name: "sc deployment reverted", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + } + + privateKey, err := crypto.GenerateKey() + require.NoError(t, err) + for _, network := range networks { + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) + require.NoError(t, err) + + ethereumClient := operations.MustGetClient(network.URL) + sourceAuth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + nonce, err := ethereumClient.NonceAt(ctx, sourceAuth.From, nil) + require.NoError(t, err) + + balance, err := ethereumClient.BalanceAt(ctx, sourceAuth.From, nil) + require.NoError(t, err) + + gasPrice, err := ethereumClient.SuggestGasPrice(ctx) + require.NoError(t, err) + + value := big.NewInt(0).Quo(balance, big.NewInt(2)) + + gas, err := ethereumClient.EstimateGas(ctx, ethereum.CallMsg{ + From: sourceAuth.From, + To: &auth.From, + GasPrice: gasPrice, + Value: value, + }) + require.NoError(t, err) + + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + To: &auth.From, + Nonce: nonce, + GasPrice: gasPrice, + Value: value, + Gas: gas, + }) + + signedTx, err := sourceAuth.Signer(sourceAuth.From, tx) + require.NoError(t, err) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + log.Debug("************************ ", tc.name, " ************************") + + for _, network := range networks { + log.Debug("------------------------ ", network.Name, " ------------------------") + ethereumClient := operations.MustGetClient(network.URL) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(0).SetUint64(network.ChainID)) + require.NoError(t, err) + + var customData map[string]interface{} + if tc.prepare != nil { + customData, err = tc.prepare(t, ctx, auth, ethereumClient) + require.NoError(t, err) + } + + signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) + require.NoError(t, err) + + balance, err := ethereumClient.BalanceAt(ctx, auth.From, nil) + require.NoError(t, err) + + log.Debugf("balance of %v: %v", auth.From, balance.String()) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + log.Debugf("tx sent: %v", signedTx.Hash().String()) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { + require.NoError(t, err) + } + + debugOptions := map[string]interface{}{ + "disableStorage": false, + "disableStack": false, + "enableMemory": true, + "enableReturnData": true, + } + + response, err := client.JSONRPCCall(network.URL, "debug_traceTransaction", signedTx.Hash().String(), debugOptions) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + results[network.Name] = response.Result + + saveTraceResultToFile(t, tc.name, network.Name, signedTx, response.Result, true) + } + + referenceValueMap := map[string]interface{}{} + err = json.Unmarshal(results[l1NetworkName], &referenceValueMap) + require.NoError(t, err) + + referenceStructLogsMap := referenceValueMap["structLogs"].([]interface{}) + + for networkName, result := range results { + if networkName == l1NetworkName { + continue + } + + resultMap := map[string]interface{}{} + err = json.Unmarshal(result, &resultMap) + require.NoError(t, err) + + require.Equal(t, referenceValueMap["failed"], resultMap["failed"], fmt.Sprintf("invalid `failed` for network %s", networkName)) + + resultStructLogsMap := resultMap["structLogs"].([]interface{}) + require.Equal(t, len(referenceStructLogsMap), len(resultStructLogsMap)) + + for structLogIndex := range referenceStructLogsMap { + referenceStructLogMap := referenceStructLogsMap[structLogIndex].(map[string]interface{}) + resultStructLogMap := resultStructLogsMap[structLogIndex].(map[string]interface{}) + + require.Equal(t, referenceStructLogMap["pc"], resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName)) + require.Equal(t, referenceStructLogMap["op"], resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s", networkName)) + require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s", networkName)) + + pc := referenceStructLogMap["pc"] + op := referenceStructLogMap["op"] + + referenceStack, found := referenceStructLogMap["stack"].([]interface{}) + if found { + resultStack := resultStructLogMap["stack"].([]interface{}) + + require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", pc, op)) + for stackIndex := range referenceStack { + require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, pc, op)) + } + } + + referenceMemory, found := referenceStructLogMap["memory"].([]interface{}) + if found { + resultMemory := resultStructLogMap["memory"].([]interface{}) + + require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", pc, op)) + for memoryIndex := range referenceMemory { + require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, pc, op)) + } + } + + referenceStorage, found := referenceStructLogMap["storage"].(map[string]interface{}) + if found { + resultStorage := resultStructLogMap["storage"].(map[string]interface{}) + + require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", pc, op)) + for storageKey, referenceStorageValue := range referenceStorage { + resultStorageValue, found := resultStorage[storageKey] + require.True(t, found, "storage address not found") + require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, pc, op)) + } + } + } + } + }) + } +} + +func TestDebugTraceBlock(t *testing.T) { + if testing.Short() { + t.Skip() + } + + const l2NetworkURL = "http://localhost:8124" + const l2ExplorerRPCComponentName = "l2-explorer-json-rpc" + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + require.NoError(t, operations.StopComponent(l2ExplorerRPCComponentName)) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + err = operations.StartComponent(l2ExplorerRPCComponentName, func() (bool, error) { return operations.NodeUpCondition(l2NetworkURL) }) + require.NoError(t, err) + + const l1NetworkName, l2NetworkName = "Local L1", "Local L2" + + networks := []struct { + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string + }{ + { + Name: l1NetworkName, + URL: operations.DefaultL1NetworkURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: l2NetworkName, + URL: l2NetworkURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + } + + results := map[string]json.RawMessage{} + + type testCase struct { + name string + blockNumberOrHash string + prepare func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) + createSignedTx func(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) + } + testCases := []testCase{ + // successful transactions + // by block number + {name: "eth transfer by number", blockNumberOrHash: "number", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment by number", blockNumberOrHash: "number", createSignedTx: createScDeploySignedTx}, + {name: "sc call by number", blockNumberOrHash: "number", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer by number", blockNumberOrHash: "number", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + // by block hash + {name: "eth transfer by hash", blockNumberOrHash: "hash", createSignedTx: createEthTransferSignedTx}, + {name: "sc deployment by hash", blockNumberOrHash: "hash", createSignedTx: createScDeploySignedTx}, + {name: "sc call by hash", blockNumberOrHash: "hash", prepare: prepareScCall, createSignedTx: createScCallSignedTx}, + {name: "erc20 transfer by hash", blockNumberOrHash: "hash", prepare: prepareERC20Transfer, createSignedTx: createERC20TransferSignedTx}, + + // failed transactions + // by block number + {name: "sc deployment reverted by number", blockNumberOrHash: "number", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted by number", blockNumberOrHash: "number", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted by number", blockNumberOrHash: "number", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + // by block hash + {name: "sc deployment reverted by hash", blockNumberOrHash: "hash", createSignedTx: createScDeployRevertedSignedTx}, + {name: "sc call reverted by hash", blockNumberOrHash: "hash", prepare: prepareScCallReverted, createSignedTx: createScCallRevertedSignedTx}, + {name: "erc20 transfer reverted by hash", blockNumberOrHash: "hash", prepare: prepareERC20TransferReverted, createSignedTx: createERC20TransferRevertedSignedTx}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + log.Debug("************************ ", tc.name, " ************************") + + for _, network := range networks { + log.Debug("------------------------ ", network.Name, " ------------------------") + ethereumClient := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + var customData map[string]interface{} + if tc.prepare != nil { + customData, err = tc.prepare(t, ctx, auth, ethereumClient) + require.NoError(t, err) + } + + signedTx, err := tc.createSignedTx(t, ctx, auth, ethereumClient, customData) + require.NoError(t, err) + + err = ethereumClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + log.Debugf("tx sent: %v", signedTx.Hash().String()) + + err = operations.WaitTxToBeMined(ctx, ethereumClient, signedTx, operations.DefaultTimeoutTxToBeMined) + if err != nil && !strings.HasPrefix(err.Error(), "transaction has failed, reason:") { + require.NoError(t, err) + } + + receipt, err := ethereumClient.TransactionReceipt(ctx, signedTx.Hash()) + require.NoError(t, err) + + debugOptions := map[string]interface{}{ + "disableStorage": false, + "disableStack": false, + "enableMemory": true, + "enableReturnData": true, + } + + var response types.Response + if tc.blockNumberOrHash == "number" { + response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByNumber", hex.EncodeBig(receipt.BlockNumber), debugOptions) + } else { + response, err = client.JSONRPCCall(network.URL, "debug_traceBlockByHash", receipt.BlockHash.String(), debugOptions) + } + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + results[network.Name] = response.Result + } + + referenceTransactions := []interface{}{} + err = json.Unmarshal(results[l1NetworkName], &referenceTransactions) + require.NoError(t, err) + + for networkName, result := range results { + if networkName == l1NetworkName { + continue + } + + resultTransactions := []interface{}{} + err = json.Unmarshal(result, &resultTransactions) + require.NoError(t, err) + + for transactionIndex := range referenceTransactions { + referenceTransactionMap := referenceTransactions[transactionIndex].(map[string]interface{}) + referenceResultMap := referenceTransactionMap["result"].(map[string]interface{}) + referenceStructLogsMap := referenceResultMap["structLogs"].([]interface{}) + + resultTransactionMap := resultTransactions[transactionIndex].(map[string]interface{}) + resultResultMap := resultTransactionMap["result"].(map[string]interface{}) + resultStructLogsMap := resultResultMap["structLogs"].([]interface{}) + + require.Equal(t, len(referenceStructLogsMap), len(resultStructLogsMap)) + + for structLogIndex := range referenceStructLogsMap { + referenceStructLogMap := referenceStructLogsMap[structLogIndex].(map[string]interface{}) + resultStructLogMap := resultStructLogsMap[structLogIndex].(map[string]interface{}) + + require.Equal(t, referenceStructLogMap["pc"], resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName)) + require.Equal(t, referenceStructLogMap["op"], resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s", networkName)) + require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s", networkName)) + + pc := referenceStructLogMap["pc"] + op := referenceStructLogMap["op"] + + referenceStack, found := referenceStructLogMap["stack"].([]interface{}) + if found { + resultStack := resultStructLogMap["stack"].([]interface{}) + + require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", pc, op)) + for stackIndex := range referenceStack { + require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, pc, op)) + } + } + + referenceMemory, found := referenceStructLogMap["memory"].([]interface{}) + if found { + resultMemory := resultStructLogMap["memory"].([]interface{}) + + require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", pc, op)) + for memoryIndex := range referenceMemory { + require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, pc, op)) + } + } + + referenceStorage, found := referenceStructLogMap["storage"].(map[string]interface{}) + if found { + resultStorage := resultStructLogMap["storage"].(map[string]interface{}) + + require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", pc, op)) + for storageKey, referenceStorageValue := range referenceStorage { + resultStorageValue, found := resultStorage[storageKey] + require.True(t, found, "storage address not found") + require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, pc, op)) + } + } + } + } + } + }) + } +} diff --git a/test/e2e/ethtransfer_test.go b/test/e2e/ethtransfer_test.go index 74569ca01a..e0ea4eeb98 100644 --- a/test/e2e/ethtransfer_test.go +++ b/test/e2e/ethtransfer_test.go @@ -3,7 +3,6 @@ package e2e import ( "context" "math/big" - "os" "testing" "time" @@ -16,15 +15,12 @@ import ( "github.com/stretchr/testify/require" ) -func init() { - os.Setenv("CONFIG_MODE", "test") -} - func TestEthTransfer(t *testing.T) { if testing.Short() { t.Skip() } + ctx := context.Background() defer func() { require.NoError(t, operations.Teardown()) }() err := operations.Teardown() @@ -43,7 +39,7 @@ func TestEthTransfer(t *testing.T) { client, err := ethclient.Dial(operations.DefaultL2NetworkURL) require.NoError(t, err) // Send txs - nTxs := 50 + nTxs := 10 amount := big.NewInt(10000) toAddress := common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8") senderBalance, err := client.BalanceAt(ctx, auth.From, nil) @@ -56,11 +52,6 @@ func TestEthTransfer(t *testing.T) { log.Infof("Sender Balance: %v", senderBalance.String()) log.Infof("Sender Nonce: %v", senderNonce) - log.Infof("Sending %d transactions...", nTxs) - var lastTxHash common.Hash - - var sentTxs []*types.Transaction - gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &toAddress, Value: amount}) require.NoError(t, err) @@ -70,47 +61,12 @@ func TestEthTransfer(t *testing.T) { nonce, err := client.PendingNonceAt(ctx, auth.From) require.NoError(t, err) + txs := make([]*types.Transaction, 0, nTxs) for i := 0; i < nTxs; i++ { tx := types.NewTransaction(nonce+uint64(i), toAddress, amount, gasLimit, gasPrice, nil) - signedTx, err := auth.Signer(auth.From, tx) - require.NoError(t, err) - log.Infof("Sending Tx %v Nonce %v", signedTx.Hash(), signedTx.Nonce()) - err = client.SendTransaction(context.Background(), signedTx) - require.NoError(t, err) - lastTxHash = signedTx.Hash() - - sentTxs = append(sentTxs, signedTx) - } - // wait for TX to be mined - timeout := 180 * time.Second - for _, tx := range sentTxs { - log.Infof("Waiting Tx %s to be mined", tx.Hash()) - err = operations.WaitTxToBeMined(client, tx.Hash(), timeout) - require.NoError(t, err) - log.Infof("Tx %s mined successfully", tx.Hash()) - - // check transaction nonce against transaction reported L2 block number - receipt, err := client.TransactionReceipt(ctx, tx.Hash()) - require.NoError(t, err) - - // get block L2 number - blockL2Number := receipt.BlockNumber - require.Equal(t, tx.Nonce(), blockL2Number.Uint64()-1) + txs = append(txs, tx) } - log.Infof("%d transactions added into the trusted state successfully.", nTxs) - - // get block L2 number of the last transaction sent - receipt, err := client.TransactionReceipt(ctx, lastTxHash) - require.NoError(t, err) - l2BlockNumber := receipt.BlockNumber - - // wait for l2 block to be virtualized - log.Infof("waiting for the block number %v to be virtualized", l2BlockNumber.String()) - err = operations.WaitL2BlockToBeVirtualized(l2BlockNumber, 4*time.Minute) - require.NoError(t, err) - // wait for l2 block number to be consolidated - log.Infof("waiting for the block number %v to be consolidated", l2BlockNumber.String()) - err = operations.WaitL2BlockToBeConsolidated(l2BlockNumber, 4*time.Minute) + _, err = operations.ApplyL2Txs(ctx, txs, auth, client, operations.VerifiedConfirmationLevel) require.NoError(t, err) } diff --git a/test/e2e/forced_batches_test.go b/test/e2e/forced_batches_test.go new file mode 100644 index 0000000000..fccd037d2e --- /dev/null +++ b/test/e2e/forced_batches_test.go @@ -0,0 +1,231 @@ +package e2e + +import ( + "context" + "math/big" + "sync" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevmglobalexitroot" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/constants" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestForcedBatches(t *testing.T) { + if testing.Short() { + t.Skip() + } + + defer func() { + require.NoError(t, operations.Teardown()) + }() + + var err error + nTxs := 10 + ctx := context.Background() + opsman, auth, client, amount, gasLimit, gasPrice, nonce := setupEnvironment(ctx, t) + + txs := make([]*types.Transaction, 0, nTxs) + for i := 0; i < nTxs; i++ { + tx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) + nonce = nonce + 1 + txs = append(txs, tx) + } + + wgNormalL2Transfers := new(sync.WaitGroup) + wgNormalL2Transfers.Add(1) + var l2BlockNumbers []*big.Int + go func() { + defer wgNormalL2Transfers.Done() + l2BlockNumbers, err = operations.ApplyL2Txs(ctx, txs, auth, client, operations.VerifiedConfirmationLevel) + require.NoError(t, err) + }() + + time.Sleep(2 * time.Second) + amount = big.NewInt(0).Add(amount, big.NewInt(10)) + unsignedTx := types.NewTransaction(nonce, toAddress, amount, gasLimit, gasPrice, nil) + signedTx, err := auth.Signer(auth.From, unsignedTx) + require.NoError(t, err) + encodedTxs, err := state.EncodeTransactions([]types.Transaction{*signedTx}) + require.NoError(t, err) + forcedBatch, err := sendForcedBatch(t, encodedTxs, opsman) + require.NoError(t, err) + + // Checking if all txs sent before the forced batch were processed within previous closed batch + wgNormalL2Transfers.Wait() + for _, l2blockNum := range l2BlockNumbers { + batch, err := opsman.State().GetBatchByL2BlockNumber(ctx, l2blockNum.Uint64(), nil) + require.NoError(t, err) + require.Less(t, batch.BatchNumber, forcedBatch.BatchNumber) + } +} + +func setupEnvironment(ctx context.Context, t *testing.T) (*operations.Manager, *bind.TransactOpts, *ethclient.Client, *big.Int, uint64, *big.Int, uint64) { + + err := operations.Teardown() + require.NoError(t, err) + opsCfg := operations.GetDefaultOperationsConfig() + opsCfg.State.MaxCumulativeGasUsed = 80000000000 + opsman, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsman.Setup() + require.NoError(t, err) + time.Sleep(5 * time.Second) + // Load account with balance on local genesis + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) + require.NoError(t, err) + // Load eth client + client, err := ethclient.Dial(operations.DefaultL2NetworkURL) + require.NoError(t, err) + // Send txs + amount := big.NewInt(10000) + senderBalance, err := client.BalanceAt(ctx, auth.From, nil) + require.NoError(t, err) + senderNonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + log.Infof("Receiver Addr: %v", toAddress.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", senderNonce) + + gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &toAddress, Value: amount}) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + return opsman, auth, client, amount, gasLimit, gasPrice, nonce +} + +func sendForcedBatch(t *testing.T, txs []byte, opsman *operations.Manager) (*state.Batch, error) { + ctx := context.Background() + st := opsman.State() + // Connect to ethereum node + ethClient, err := ethclient.Dial(operations.DefaultL1NetworkURL) + require.NoError(t, err) + + initialGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) + require.NoError(t, err) + + // Create smc client + zkEvmAddr := common.HexToAddress(operations.DefaultL1ZkEVMSmartContract) + zkEvm, err := polygonzkevm.NewPolygonzkevm(zkEvmAddr, ethClient) + require.NoError(t, err) + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + require.NoError(t, err) + + log.Info("Using address: ", auth.From) + + num, err := zkEvm.LastForceBatch(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + log.Info("Number of forceBatches in the smc: ", num) + + // Get tip + tip, err := zkEvm.GetForcedBatchFee(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + managerAddress, err := zkEvm.GlobalExitRootManager(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + manager, err := polygonzkevmglobalexitroot.NewPolygonzkevmglobalexitroot(managerAddress, ethClient) + require.NoError(t, err) + + rootInContract, err := manager.GetLastGlobalExitRoot(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + rootInContractHash := common.BytesToHash(rootInContract[:]) + + disallowed, err := zkEvm.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + if disallowed { + tx, err := zkEvm.ActivateForceBatches(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + // Send forceBatch + tx, err := zkEvm.ForceBatch(auth, txs, tip) + require.NoError(t, err) + + log.Info("TxHash: ", tx.Hash()) + time.Sleep(1 * time.Second) + + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + query := ethereum.FilterQuery{ + FromBlock: currentBlock.Number(), + Addresses: []common.Address{zkEvmAddr}, + } + logs, err := ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + + var forcedBatch *state.Batch + for _, vLog := range logs { + if vLog.Topics[0] != constants.ForcedBatchSignatureHash { + logs, err = ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + continue + } + fb, err := zkEvm.ParseForceBatch(vLog) + if err != nil { + log.Errorf("failed to parse force batch log event, err: ", err) + } + log.Debugf("log decoded: %+v", fb) + ger := fb.LastGlobalExitRoot + log.Info("GlobalExitRoot: ", ger) + log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) + fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) + return nil, err + } + log.Info("MinForcedTimestamp: ", fullBlock.Time()) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + for err == state.ErrStateNotSynchronized { + time.Sleep(1 * time.Second) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + } + log.Info("ForcedBatchNum: ", forcedBatch.BatchNumber) + require.NoError(t, err) + require.NotNil(t, forcedBatch) + + log.Info("Waiting for batch to be virtualized...") + err = operations.WaitBatchToBeVirtualized(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + log.Info("Waiting for batch to be consolidated...") + err = operations.WaitBatchToBeConsolidated(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + if rootInContractHash != initialGer.GlobalExitRoot { + finalGer, _, err := st.GetLatestGer(ctx, gerFinalityBlocks) + require.NoError(t, err) + if finalGer.GlobalExitRoot != rootInContractHash { + log.Fatal("global exit root is not updated") + } + } + } + + return forcedBatch, nil +} diff --git a/test/e2e/forced_batches_vector_test.go b/test/e2e/forced_batches_vector_test.go new file mode 100644 index 0000000000..b4eb1d2a51 --- /dev/null +++ b/test/e2e/forced_batches_vector_test.go @@ -0,0 +1,228 @@ +package e2e + +import ( + "context" + "math/big" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/constants" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/vectors" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestForcedBatchesVectorFiles(t *testing.T) { + + if testing.Short() { + t.Skip() + } + vectorFilesDir := "./../vectors/src/state-transition/forced-tx" + ctx := context.Background() + err := filepath.Walk(vectorFilesDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && !strings.HasSuffix(info.Name(), "list.json") { + + t.Run(info.Name(), func(t *testing.T) { + + defer func() { + require.NoError(t, operations.Teardown()) + }() + + // Load test vectors + log.Info("=====================================================================") + log.Info(path) + log.Info("=====================================================================") + testCase, err := vectors.LoadStateTransitionTestCaseV2(path) + require.NoError(t, err) + + opsCfg := operations.GetDefaultOperationsConfig() + opsCfg.State.MaxCumulativeGasUsed = 80000000000 + opsman, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + + // Setting Genesis + log.Info("###################") + log.Info("# Setting Genesis #") + log.Info("###################") + genesisActions := vectors.GenerateGenesisActions(testCase.Genesis) + require.NoError(t, opsman.SetGenesis(genesisActions)) + require.NoError(t, opsman.Setup()) + + // Check initial root + log.Info("################################") + log.Info("# Verifying initial state root #") + log.Info("################################") + actualOldStateRoot, err := opsman.State().GetLastStateRoot(ctx, nil) + require.NoError(t, err) + require.Equal(t, testCase.ExpectedOldStateRoot, actualOldStateRoot.Hex()) + decodedData, err := hex.DecodeHex(testCase.BatchL2Data) + require.NoError(t, err) + _, txBytes, err := state.DecodeTxs(decodedData) + forcedBatch, err := sendForcedBatchForVector(t, txBytes, opsman) + require.NoError(t, err) + actualNewStateRoot := forcedBatch.StateRoot + isClosed, err := opsman.State().IsBatchClosed(ctx, forcedBatch.BatchNumber, nil) + require.NoError(t, err) + + // wait until is closed + for !isClosed { + time.Sleep(1 * time.Second) + isClosed, err = opsman.State().IsBatchClosed(ctx, forcedBatch.BatchNumber, nil) + require.NoError(t, err) + } + + log.Info("#######################") + log.Info("# Verifying new leafs #") + log.Info("#######################") + merkleTree := opsman.State().GetTree() + for _, expectedNewLeaf := range testCase.ExpectedNewLeafs { + if expectedNewLeaf.IsSmartContract { + log.Info("Smart Contract Address: ", expectedNewLeaf.Address) + } else { + log.Info("Account Address: ", expectedNewLeaf.Address) + } + log.Info("Verifying Balance...") + actualBalance, err := merkleTree.GetBalance(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.Balance.String(), actualBalance.String()) + + log.Info("Verifying Nonce...") + actualNonce, err := merkleTree.GetNonce(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.Nonce, actualNonce.String()) + if expectedNewLeaf.IsSmartContract { + log.Info("Verifying Storage...") + for positionHex, expectedNewStorageHex := range expectedNewLeaf.Storage { + position, ok := big.NewInt(0).SetString(positionHex[2:], 16) + require.True(t, ok) + expectedNewStorage, ok := big.NewInt(0).SetString(expectedNewStorageHex[2:], 16) + require.True(t, ok) + actualStorage, err := merkleTree.GetStorageAt(ctx, common.HexToAddress(expectedNewLeaf.Address), position, actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewStorage, actualStorage) + } + + log.Info("Verifying HashBytecode...") + actualHashByteCode, err := merkleTree.GetCodeHash(ctx, common.HexToAddress(expectedNewLeaf.Address), actualNewStateRoot.Bytes()) + require.NoError(t, err) + require.Equal(t, expectedNewLeaf.HashBytecode, common.BytesToHash(actualHashByteCode).String()) + } + } + return + }) + + return nil + } + return nil + }) + require.NoError(t, err) +} + +func sendForcedBatchForVector(t *testing.T, txs []byte, opsman *operations.Manager) (*state.Batch, error) { + ctx := context.Background() + st := opsman.State() + // Connect to ethereum node + ethClient, err := ethclient.Dial(operations.DefaultL1NetworkURL) + require.NoError(t, err) + + // Create smc client + zkEvmAddr := common.HexToAddress(operations.DefaultL1ZkEVMSmartContract) + zkEvm, err := polygonzkevm.NewPolygonzkevm(zkEvmAddr, ethClient) + require.NoError(t, err) + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + require.NoError(t, err) + + log.Info("Using address: ", auth.From) + num, err := zkEvm.LastForceBatch(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + log.Info("Number of forceBatches in the smc: ", num) + + // Get tip + tip, err := zkEvm.GetForcedBatchFee(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + disallowed, err := zkEvm.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + if disallowed { + tx, err := zkEvm.ActivateForceBatches(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + // Send forceBatch + tx, err := zkEvm.ForceBatch(auth, txs, tip) + require.NoError(t, err) + + log.Info("Forced Batch Submit to L1 TxHash: ", tx.Hash()) + time.Sleep(1 * time.Second) + + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + query := ethereum.FilterQuery{ + FromBlock: currentBlock.Number(), + Addresses: []common.Address{zkEvmAddr}, + } + logs, err := ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + + var forcedBatch *state.Batch + for _, vLog := range logs { + if vLog.Topics[0] != constants.ForcedBatchSignatureHash { + logs, err = ethClient.FilterLogs(ctx, query) + require.NoError(t, err) + continue + } + fb, err := zkEvm.ParseForceBatch(vLog) + if err != nil { + log.Errorf("failed to parse force batch log event, err: ", err) + } + log.Debugf("log decoded: %+v", fb) + ger := fb.LastGlobalExitRoot + log.Info("GlobalExitRoot: ", ger) + log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) + fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) + return nil, err + } + log.Info("MinForcedTimestamp: ", fullBlock.Time()) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + for err == state.ErrStateNotSynchronized { + time.Sleep(1 * time.Second) + forcedBatch, err = st.GetBatchByForcedBatchNum(ctx, fb.ForceBatchNum, nil) + } + require.NoError(t, err) + require.NotNil(t, forcedBatch) + + log.Info("Waiting Forced Batch to be virtualized ...") + err = operations.WaitBatchToBeVirtualized(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + + log.Info("Waiting Forced Batch to be consolidated ...") + err = operations.WaitBatchToBeConsolidated(forcedBatch.BatchNumber, 4*time.Minute, st) + require.NoError(t, err) + } + + return forcedBatch, nil +} diff --git a/test/e2e/jsonrpc1_test.go b/test/e2e/jsonrpc1_test.go new file mode 100644 index 0000000000..a75b03a345 --- /dev/null +++ b/test/e2e/jsonrpc1_test.go @@ -0,0 +1,536 @@ +package e2e + +import ( + "context" + "encoding/json" + "math/big" + "reflect" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Double" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/EmitLog" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestJSONRPC tests JSON RPC methods on a running environment. +func TestJSONRPC(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + for _, network := range networks { + log.Infof("Network %s", network.Name) + sc, err := deployContracts(network.URL, operations.DefaultSequencerPrivateKey, network.ChainID) + require.NoError(t, err) + + callOpts := &bind.CallOpts{Pending: false} + + payload := big.NewInt(5) + number, err := sc.Double(callOpts, payload) + require.NoError(t, err) + expected := big.NewInt(0).Mul(payload, big.NewInt(2)) + require.Equal(t, expected, number) + } +} + +func deployContracts(url, privateKey string, chainId uint64) (*Double.Double, error) { + ctx := context.Background() + client := operations.MustGetClient(url) + auth := operations.MustGetAuth(privateKey, chainId) + + _, scTx, sc, err := Double.DeployDouble(auth, client) + if err != nil { + return nil, err + } + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + if err != nil { + return nil, err + } + + return sc, nil +} + +func Test_Filters(t *testing.T) { + if testing.Short() { + t.Skip() + } + ctx := context.Background() + setup() + defer teardown() + for _, network := range networks { + // test newBlockFilter creation + log.Infof("Network %s", network.Name) + response, err := client.JSONRPCCall(network.URL, "eth_newBlockFilter") + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + var filterId string + err = json.Unmarshal(response.Result, &filterId) + require.NoError(t, err) + require.NotEmpty(t, filterId) + + // test newFilter creation with block range and block hash + response, err = client.JSONRPCCall(network.URL, "eth_newFilter", map[string]interface{}{ + "BlockHash": common.HexToHash("0x1"), + "FromBlock": "0x1", + "ToBlock": "0x2", + }) + require.NoError(t, err) + require.NotNil(t, response.Error) + require.Equal(t, invalidParamsErrorCode, response.Error.Code) + require.Equal(t, "invalid argument 0: cannot specify both BlockHash and FromBlock/ToBlock, choose one or the other", response.Error.Message) + + // test newFilter creation with block hash + response, err = client.JSONRPCCall(network.URL, "eth_newFilter", map[string]interface{}{ + "BlockHash": common.HexToHash("0x1"), + "Addresses": []common.Address{ + common.HexToAddress("0x2"), + }, + "Topics": [][]common.Hash{ + {common.HexToHash("0x3")}, + }, + }) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + filterId = "" + err = json.Unmarshal(response.Result, &filterId) + require.NoError(t, err) + require.NotEmpty(t, filterId) + + // test newFilter creation with block range + response, err = client.JSONRPCCall(network.URL, "eth_newFilter", map[string]interface{}{ + "FromBlock": "0x1", + "ToBlock": "0x2", + "Addresses": []common.Address{ + common.HexToAddress("0x2"), + }, + "Topics": [][]common.Hash{ + {common.HexToHash("0x3")}, + }, + }) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + filterId = "" + err = json.Unmarshal(response.Result, &filterId) + require.NoError(t, err) + require.NotEmpty(t, filterId) + + // test uninstallFilter when filter is installed + response, err = client.JSONRPCCall(network.URL, "eth_uninstallFilter", filterId) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + var uninstalled bool + err = json.Unmarshal(response.Result, &uninstalled) + require.NoError(t, err) + require.True(t, uninstalled) + + // test uninstallFilter when filter doesn't exist or was already uninstalled + response, err = client.JSONRPCCall(network.URL, "eth_uninstallFilter", filterId) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + uninstalled = true + err = json.Unmarshal(response.Result, &uninstalled) + require.NoError(t, err) + require.False(t, uninstalled) + + ethereumClient := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + // test getFilterChanges for a blockFilter ID + blockBeforeFilter, err := ethereumClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + + response, err = client.JSONRPCCall(network.URL, "eth_newBlockFilter") + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + var blockFilterId string + err = json.Unmarshal(response.Result, &blockFilterId) + require.NoError(t, err) + require.NotEmpty(t, blockFilterId) + + // force a block to be generated sending a eth transfer tx + tx, err := createTX(ethereumClient, auth, toAddress, big.NewInt(1000)) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + blockAfterFilter, err := ethereumClient.BlockByNumber(ctx, nil) + require.NoError(t, err) + + response, err = client.JSONRPCCall(network.URL, "eth_getFilterChanges", blockFilterId) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + var blockFilterChanges []common.Hash + err = json.Unmarshal(response.Result, &blockFilterChanges) + require.NoError(t, err) + + assert.NotEqual(t, blockBeforeFilter.Hash().String(), blockFilterChanges[0].String()) + assert.Equal(t, blockAfterFilter.Hash().String(), blockFilterChanges[len(blockFilterChanges)-1].String()) + + // test getFilterChanges for a logFilter ID + // create a SC to emit some logs + scAddr, scTx, sc, err := EmitLog.DeployEmitLog(auth, ethereumClient) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, scTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + response, err = client.JSONRPCCall(network.URL, "eth_newFilter", map[string]interface{}{ + "Addresses": []common.Address{scAddr}, + }) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + logFilterId := "" + err = json.Unmarshal(response.Result, &logFilterId) + require.NoError(t, err) + require.NotEmpty(t, logFilterId) + + // emit logs + tx, err = sc.EmitLogs(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + logs, err := ethereumClient.FilterLogs(ctx, ethereum.FilterQuery{Addresses: []common.Address{scAddr}}) + require.NoError(t, err) + + response, err = client.JSONRPCCall(network.URL, "eth_getFilterChanges", logFilterId) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + var logFilterChanges []ethTypes.Log + err = json.Unmarshal(response.Result, &logFilterChanges) + require.NoError(t, err) + + assert.Equal(t, 10, len(logs)) + assert.Equal(t, 10, len(logFilterChanges)) + assert.True(t, reflect.DeepEqual(logs, logFilterChanges)) + + // emit more logs + tx, err = sc.EmitLogs(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + tx, err = sc.EmitLogs(auth) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + logs, err = ethereumClient.FilterLogs(ctx, ethereum.FilterQuery{Addresses: []common.Address{scAddr}}) + require.NoError(t, err) + + response, err = client.JSONRPCCall(network.URL, "eth_getFilterChanges", logFilterId) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + err = json.Unmarshal(response.Result, &logFilterChanges) + require.NoError(t, err) + + assert.Equal(t, 30, len(logs)) + assert.Equal(t, 20, len(logFilterChanges)) + } +} + +func Test_Gas(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + var Address1 = toAddress + var Values = []*big.Int{ + big.NewInt(1000), + big.NewInt(10000000), + big.NewInt(100000000000), + big.NewInt(1000000000000000), + } + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + for _, value := range Values { + client, err := ethclient.Dial(network.URL) + require.NoError(t, err) + msg := ethereum.CallMsg{From: common.HexToAddress(operations.DefaultSequencerAddress), + To: &Address1, + Value: value} + + balance, err := client.BalanceAt(context.Background(), common.HexToAddress(operations.DefaultSequencerAddress), nil) + require.NoError(t, err) + + log.Infof("Balance: %d", balance) + require.GreaterOrEqual(t, balance.Cmp(big.NewInt(1)), 1) + + response, err := client.EstimateGas(context.Background(), msg) + require.NoError(t, err) + require.NotNil(t, response) + log.Infof("Estimated gas: %d", response) + require.GreaterOrEqual(t, response, uint64(21000)) + } + } +} + +func Test_Block(t *testing.T) { + if testing.Short() { + t.Skip() + } + ctx := context.Background() + setup() + defer teardown() + type rpcTx struct { + BlockHash string `json:"blockHash"` + BlockNumber string `json:"blockNumber"` + ChainID string `json:"chainId"` + From string `json:"from"` + Gas string `json:"gas"` + GasPrice string `json:"gasPrice"` + Hash string `json:"hash"` + Input string `json:"input"` + Nonce string `json:"nonce"` + PublicKey string `json:"publicKey"` + R string `json:"r"` + Raw string `json:"raw"` + S string `json:"s"` + To string `json:"to"` + TransactionIndex string `json:"transactionIndex"` + V string `json:"v"` + Value string `json:"value"` + } + + for _, network := range networks { + log.Infof("Network %s", network.Name) + ethereumClient, err := ethclient.Dial(network.URL) + require.NoError(t, err) + auth, err := operations.GetAuth(network.PrivateKey, network.ChainID) + require.NoError(t, err) + + tx, err := createTX(ethereumClient, auth, toAddress, big.NewInt(1000)) + require.NoError(t, err) + // no block number yet... will wait + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + receipt, err := ethereumClient.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + require.Equal(t, receipt.TxHash, tx.Hash()) + require.Equal(t, receipt.Type, tx.Type()) + require.Equal(t, uint(0), receipt.TransactionIndex) + + blockNumber, err := ethereumClient.BlockNumber(ctx) + require.NoError(t, err) + log.Infof("\nBlock num %d", blockNumber) + require.GreaterOrEqual(t, blockNumber, receipt.BlockNumber.Uint64()) + + block, err := ethereumClient.BlockByNumber(ctx, receipt.BlockNumber) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, receipt.BlockNumber.Uint64(), block.Number().Uint64()) + require.Equal(t, receipt.BlockHash.String(), block.Hash().String()) + + block, err = ethereumClient.BlockByHash(ctx, receipt.BlockHash) + require.NoError(t, err) + require.NotNil(t, block) + require.Equal(t, receipt.BlockNumber.Uint64(), block.Number().Uint64()) + require.Equal(t, receipt.BlockHash.String(), block.Hash().String()) + + nonExistentBlockNumber := big.NewInt(0).SetUint64(blockNumber + uint64(1)) + block, err = ethereumClient.BlockByNumber(ctx, nonExistentBlockNumber) + require.Error(t, err) + require.Nil(t, block) + + nonExistentBlockHash := common.HexToHash("0xFFFFFF") + block, err = ethereumClient.BlockByHash(ctx, nonExistentBlockHash) + require.Error(t, err) + require.Nil(t, block) + // its pending + + response, err := client.JSONRPCCall(network.URL, "eth_getBlockTransactionCountByNumber", hexutil.EncodeBig(receipt.BlockNumber)) + require.NoError(t, err) + require.Nil(t, response.Error) + require.NotNil(t, response.Result) + + txCount := "" + err = json.Unmarshal(response.Result, &txCount) + require.NoError(t, err) + require.Equal(t, "0x1", txCount) + + // check if block number is correct + count, err := ethereumClient.TransactionCount(ctx, receipt.BlockHash) + require.NoError(t, err) + require.Equal(t, uint(1), count) + + tx = nil + tx, err = ethereumClient.TransactionInBlock(ctx, receipt.BlockHash, receipt.TransactionIndex) + require.NoError(t, err) + require.Equal(t, receipt.TxHash, tx.Hash()) + + raw, err := client.JSONRPCCall(network.URL, "eth_getTransactionByBlockNumberAndIndex", hexutil.EncodeBig(receipt.BlockNumber), "0x0") + require.NoError(t, err) + require.Nil(t, raw.Error) + require.NotNil(t, raw.Result) + + var newTx rpcTx + err = json.Unmarshal(raw.Result, &newTx) + require.NoError(t, err) + + raw, err = client.JSONRPCCall(network.URL, "eth_getTransactionByBlockNumberAndIndex", "0x123", "0x8659") + require.NoError(t, err) + require.Nil(t, raw.Error) + require.NotNil(t, raw.Result) + + var empty rpcTx + err = json.Unmarshal(raw.Result, &empty) + require.NoError(t, err) + + // Checks for empty, when the lookup fail we get an empty struct and no errors... + v := reflect.ValueOf(empty) + + for i := 0; i < v.NumField(); i++ { + require.Empty(t, v.Field(i).Interface()) + } + + // checks for successful query + + require.Equal(t, hexutil.EncodeBig(receipt.BlockNumber), newTx.BlockNumber) + require.Equal(t, receipt.BlockHash.String(), newTx.BlockHash) + require.Equal(t, hexutil.EncodeUint64(tx.Nonce()), newTx.Nonce) + require.Equal(t, hexutil.EncodeBig(tx.ChainId()), newTx.ChainID) + } +} + +func Test_Transactions(t *testing.T) { + if testing.Short() { + t.Skip() + } + ctx := context.Background() + setup() + defer teardown() + for _, network := range networks { + log.Infof("Network %s", network.Name) + ethClient, err := ethclient.Dial(network.URL) + require.NoError(t, err) + auth, err := operations.GetAuth(network.PrivateKey, network.ChainID) + require.NoError(t, err) + + // Test Case: Successful transfer + tx, err := createTX(ethClient, auth, toAddress, big.NewInt(100000)) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + // Test Case: get transaction by block number and index + receipt, err := ethClient.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + require.NotNil(t, receipt) + res, err := client.JSONRPCCall(network.URL, "eth_getTransactionByBlockNumberAndIndex", hex.EncodeBig(receipt.BlockNumber), hex.EncodeUint64(uint64(receipt.TransactionIndex))) + require.NoError(t, err) + require.Nil(t, res.Error) + require.NotNil(t, res.Result) + var txByBlockNumberAndIndex *types.Transaction + err = json.Unmarshal(res.Result, &txByBlockNumberAndIndex) + require.NoError(t, err) + + require.Equal(t, tx.Hash().String(), txByBlockNumberAndIndex.Hash.String()) + + // Test Case: get transaction by block hash and index + receipt, err = ethClient.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + require.NotNil(t, receipt) + txByBlockHashAndIndex, err := ethClient.TransactionInBlock(ctx, receipt.BlockHash, receipt.TransactionIndex) + require.NoError(t, err) + require.Equal(t, tx.Hash().String(), txByBlockHashAndIndex.Hash().String()) + + // Setup for test cases + nonce, err := ethClient.NonceAt(context.Background(), auth.From, nil) + require.NoError(t, err) + + gasLimit, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{From: auth.From, To: &toAddress, Value: big.NewInt(10000)}) + require.NoError(t, err) + + gasPrice, err := ethClient.SuggestGasPrice(context.Background()) + require.NoError(t, err) + + // Test Case: TX with invalid nonce + tx = ethTypes.NewTransaction(nonce-1, // Nonce will be lower than the current getNonceAt() + toAddress, big.NewInt(100), gasLimit, gasPrice, nil) + signedTx, err := auth.Signer(auth.From, tx) + require.NoError(t, err) + + log.Infof("Sending Tx %v Nonce (invalid) %v", signedTx.Hash(), signedTx.Nonce()) + err = ethClient.SendTransaction(context.Background(), signedTx) + require.ErrorContains(t, err, "nonce too low") + // End Test Case + + // Test Case: TX with no signature (which would fail the EIP-155) + invalidTx := ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: nonce, + Value: big.NewInt(10000), + Gas: gasLimit, + GasPrice: gasPrice, + Data: nil, + }) + err = ethClient.SendTransaction(context.Background(), invalidTx) + require.Error(t, err) + // End Test Case + + // Test Case: TX with amount being higher than balance + balance, err := ethClient.BalanceAt(context.Background(), auth.From, nil) + require.NoError(t, err) + + nonce, err = ethClient.NonceAt(context.Background(), auth.From, nil) + require.NoError(t, err) + + log.Infof("Balance: %d", balance) + + tx = ethTypes.NewTransaction(nonce, toAddress, big.NewInt(0).Add(balance, big.NewInt(10)), gasLimit, gasPrice, nil) + signedTx, err = auth.Signer(auth.From, tx) + require.NoError(t, err) + + log.Infof("Sending Tx %v Nonce %v", signedTx.Hash(), signedTx.Nonce()) + err = ethClient.SendTransaction(context.Background(), signedTx) + require.ErrorContains(t, err, pool.ErrInsufficientFunds.Error()) + + // no contract code at given address test + // deploy contract with not enough gas for storage, just execution + address := common.HexToAddress("0xDEADBEEF596a836C9063a7EE35dA94DDA3b57B62") + instance, err := Double.NewDouble(address, ethClient) + require.NoError(t, err) + + callOpts := &bind.CallOpts{Pending: false} + + payload := big.NewInt(5) + _, err = instance.Double(callOpts, payload) + require.ErrorContains(t, err, "no contract code at given address") + } +} diff --git a/test/e2e/jsonrpc2_test.go b/test/e2e/jsonrpc2_test.go new file mode 100644 index 0000000000..10b534abc8 --- /dev/null +++ b/test/e2e/jsonrpc2_test.go @@ -0,0 +1,472 @@ +package e2e + +import ( + "context" + "encoding/json" + "math/big" + "strings" + "testing" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Revert" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Revert2" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Storage" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + "github.com/gorilla/websocket" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_Misc(t *testing.T) { + if testing.Short() { + t.Skip() + } + ctx := context.Background() + setup() + defer teardown() + for _, network := range networks { + log.Infof("Network %s", network.Name) + + ethereumClient, err := ethclient.Dial(network.URL) + require.NoError(t, err) + + // ChainId() + chainId, err := ethereumClient.ChainID(ctx) + require.NoError(t, err) + require.Equal(t, network.ChainID, chainId.Uint64()) + + // Syncing() + progress, err := ethereumClient.SyncProgress(ctx) + require.NoError(t, err) + if progress != nil { + log.Info("Its syncing") + blockNumber, err := ethereumClient.BlockNumber(ctx) + require.NoError(t, err) + // if it's actually syncing + require.Equal(t, uint64(0x0), progress.StartingBlock) + require.Equal(t, blockNumber, progress.CurrentBlock) + } + + // GetStorageAt() + + // first deploy sample smart contract + sc_payload := int64(42) + sc_retrieve := common.HexToHash("0x2a") + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, network.ChainID) + require.NoError(t, err) + contractAddress, tx, storageSC, err := Storage.DeployStorage(auth, ethereumClient) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + tx, err = storageSC.Store(auth, big.NewInt(sc_payload)) + require.NoError(t, err) + err = operations.WaitTxToBeMined(ctx, ethereumClient, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + storage, err := ethereumClient.StorageAt(ctx, contractAddress, common.HexToHash("0x0"), nil) + require.NoError(t, err) + // in bytes but has to be hash 0x0...42 + require.Equal(t, sc_retrieve, common.BytesToHash(storage)) + + // eth_getCode + + scBytecode, err := ethereumClient.CodeAt(ctx, contractAddress, nil) + require.NoError(t, err) + require.Contains(t, Storage.StorageMetaData.Bin, common.Bytes2Hex(scBytecode)) + + emptyBytecode, err := ethereumClient.CodeAt(ctx, common.HexToAddress("0xdeadbeef"), nil) + require.NoError(t, err) + require.Empty(t, emptyBytecode) + + // check for request having more params than required: + + response, err := client.JSONRPCCall(network.URL, "eth_chainId", common.HexToHash("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"), "latest") + require.NoError(t, err) + require.NotNil(t, response.Error) + require.Nil(t, response.Result) + require.Equal(t, invalidParamsErrorCode, response.Error.Code) + require.Equal(t, "too many arguments, want at most 0", response.Error.Message) + } +} + +func Test_WebSocketsRequest(t *testing.T) { + if testing.Short() { + t.Skip() + } + ctx := context.Background() + setup() + defer teardown() + + acc := common.HexToAddress(operations.DefaultSequencerAddress) + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + client, err := ethclient.Dial(network.URL) + require.NoError(t, err) + + expectedBalance, err := client.BalanceAt(ctx, acc, nil) + require.NoError(t, err) + + wsConn, _, err := websocket.DefaultDialer.Dial(network.WebSocketURL, nil) + require.NoError(t, err) + + receivedMessages := make(chan []byte) + go func() { + for { + _, message, err := wsConn.ReadMessage() + require.NoError(t, err) + receivedMessages <- message + wsConn.Close() + break + } + }() + + params := []string{acc.String(), "latest"} + jParam, err := json.Marshal(params) + require.NoError(t, err) + + req := types.Request{JSONRPC: "2.0", ID: float64(1), Method: "eth_getBalance", Params: jParam} + jReq, _ := json.Marshal(req) + + err = wsConn.WriteMessage(websocket.TextMessage, jReq) + require.NoError(t, err) + + receivedMessage := <-receivedMessages + + resp := types.Response{} + err = json.Unmarshal(receivedMessage, &resp) + require.NoError(t, err) + + assert.Equal(t, req.JSONRPC, resp.JSONRPC) + assert.Equal(t, req.ID, resp.ID) + assert.Nil(t, resp.Error) + assert.NotNil(t, resp.Result) + + result := "" + err = json.Unmarshal(resp.Result, &result) + require.NoError(t, err) + + str := strings.TrimPrefix(result, "0x") + balance := hex.DecodeBig(str) + require.NoError(t, err) + + assert.Equal(t, expectedBalance.String(), balance.String()) + } +} + +func Test_WebSocketsSubscription(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + wsConn, _, err := websocket.DefaultDialer.Dial(network.WebSocketURL, nil) + require.NoError(t, err) + + receivedMessages := make(chan []byte) + go func() { + for { + _, message, err := wsConn.ReadMessage() + require.NoError(t, err) + receivedMessages <- message + break + } + }() + + params := []string{"newHeads"} + jParam, err := json.Marshal(params) + require.NoError(t, err) + + req := types.Request{JSONRPC: "2.0", ID: float64(1), Method: "eth_subscribe", Params: jParam} + jReq, _ := json.Marshal(req) + + err = wsConn.WriteMessage(websocket.TextMessage, jReq) + require.NoError(t, err) + + subscriptionMessage := <-receivedMessages + + resp := types.Response{} + err = json.Unmarshal(subscriptionMessage, &resp) + require.NoError(t, err) + + assert.Equal(t, req.JSONRPC, resp.JSONRPC) + assert.Equal(t, req.ID, resp.ID) + assert.Nil(t, resp.Error) + assert.NotNil(t, resp.Result) + + subscription := "" + err = json.Unmarshal(resp.Result, &subscription) + require.NoError(t, err) + + assert.NotEmpty(t, subscription) + + const numberOfBlocks = 3 + + go func() { + for i := 0; i <= numberOfBlocks; i++ { + _, message, err := wsConn.ReadMessage() + require.NoError(t, err) + receivedMessages <- message + } + wsConn.Close() + }() + + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + for i := 0; i <= numberOfBlocks; i++ { + tx, err := createTX(client, auth, toAddress, big.NewInt(1000000000)) + require.NoError(t, err) + err = operations.WaitTxToBeMined(context.Background(), client, tx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + } + + for i := 0; i <= numberOfBlocks; i++ { + receivedMessage := <-receivedMessages + resp := types.SubscriptionResponse{} + + err = json.Unmarshal(receivedMessage, &resp) + require.NoError(t, err) + + assert.Equal(t, req.JSONRPC, resp.JSONRPC) + assert.Equal(t, "eth_subscription", resp.Method) + assert.Equal(t, subscription, resp.Params.Subscription) + + block := map[string]interface{}{} + err = json.Unmarshal(resp.Params.Result, &block) + require.NoError(t, err) + assert.NotEmpty(t, block["hash"].(string)) + } + } +} + +func Test_RevertOnConstructorTransaction(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + + ctx := context.Background() + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + auth.GasLimit = 1000000 + + _, scTx, _, err := Revert.DeployRevert(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + errMsg := err.Error() + prefix := "transaction has failed, reason: execution reverted: Today is not juernes" + hasPrefix := strings.HasPrefix(errMsg, prefix) + require.True(t, hasPrefix) + + receipt, err := client.TransactionReceipt(ctx, scTx.Hash()) + require.NoError(t, err) + + assert.Equal(t, receipt.Status, ethTypes.ReceiptStatusFailed) + + msg := ethereum.CallMsg{ + From: auth.From, + To: scTx.To(), + Gas: scTx.Gas(), + + Value: scTx.Value(), + Data: scTx.Data(), + } + result, err := client.CallContract(ctx, msg, receipt.BlockNumber) + require.NotNil(t, err) + require.Nil(t, result) + rpcErr := err.(rpc.Error) + assert.Equal(t, 3, rpcErr.ErrorCode()) + assert.Equal(t, "execution reverted: Today is not juernes", rpcErr.Error()) + + dataErr := err.(rpc.DataError) + data := dataErr.ErrorData().(string) + decodedData := hex.DecodeBig(data) + unpackedData, err := abi.UnpackRevert(decodedData.Bytes()) + require.NoError(t, err) + assert.Equal(t, "Today is not juernes", unpackedData) + } +} + +func Test_RevertOnSCCallTransaction(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + + ctx := context.Background() + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + auth.GasLimit = 1000000 + + _, scTx, sc, err := Revert2.DeployRevert2(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + tx, err := sc.GenerateError(auth) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + errMsg := err.Error() + prefix := "transaction has failed, reason: execution reverted: Today is not juernes" + hasPrefix := strings.HasPrefix(errMsg, prefix) + require.True(t, hasPrefix) + + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + + assert.Equal(t, receipt.Status, ethTypes.ReceiptStatusFailed) + + msg := ethereum.CallMsg{ + From: auth.From, + To: tx.To(), + Gas: tx.Gas(), + + Value: tx.Value(), + Data: tx.Data(), + } + result, err := client.CallContract(ctx, msg, receipt.BlockNumber) + require.NotNil(t, err) + require.Nil(t, result) + rpcErr := err.(rpc.Error) + assert.Equal(t, 3, rpcErr.ErrorCode()) + assert.Equal(t, "execution reverted: Today is not juernes", rpcErr.Error()) + + dataErr := err.(rpc.DataError) + data := dataErr.ErrorData().(string) + decodedData := hex.DecodeBig(data) + unpackedData, err := abi.UnpackRevert(decodedData.Bytes()) + require.NoError(t, err) + assert.Equal(t, "Today is not juernes", unpackedData) + } +} + +func Test_RevertOnSCCallGasEstimation(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + + ctx := context.Background() + + for _, network := range networks { + log.Infof("Network %s", network.Name) + + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + auth.GasLimit = 1000000 + + _, scTx, sc, err := Revert2.DeployRevert2(auth, client) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + tx, err := sc.GenerateError(auth) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) + errMsg := err.Error() + prefix := "transaction has failed, reason: execution reverted: Today is not juernes" + hasPrefix := strings.HasPrefix(errMsg, prefix) + require.True(t, hasPrefix) + + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + + assert.Equal(t, receipt.Status, ethTypes.ReceiptStatusFailed) + + msg := ethereum.CallMsg{ + From: auth.From, + To: tx.To(), + Gas: tx.Gas(), + + Value: tx.Value(), + Data: tx.Data(), + } + result, err := client.EstimateGas(ctx, msg) + require.NotNil(t, err) + require.Equal(t, uint64(0), result) + rpcErr := err.(rpc.Error) + assert.Equal(t, 3, rpcErr.ErrorCode()) + assert.Equal(t, "execution reverted: Today is not juernes", rpcErr.Error()) + + dataErr := err.(rpc.DataError) + data := dataErr.ErrorData().(string) + decodedData := hex.DecodeBig(data) + unpackedData, err := abi.UnpackRevert(decodedData.Bytes()) + require.NoError(t, err) + assert.Equal(t, "Today is not juernes", unpackedData) + } +} + +func TestCallMissingParameters(t *testing.T) { + if testing.Short() { + t.Skip() + } + setup() + defer teardown() + + type testCase struct { + name string + params []interface{} + expectedError types.ErrorObject + } + + testCases := []testCase{ + { + name: "params is empty", + params: []interface{}{}, + expectedError: types.ErrorObject{Code: types.InvalidParamsErrorCode, Message: "missing value for required argument 0"}, + }, + { + name: "params has only first parameter", + params: []interface{}{map[string]interface{}{"value": "0x1"}}, + expectedError: types.ErrorObject{Code: types.InvalidParamsErrorCode, Message: "missing value for required argument 1"}, + }, + } + + for _, network := range networks { + log.Infof("Network %s", network.Name) + for _, testCase := range testCases { + t.Run(network.Name+testCase.name, func(t *testing.T) { + response, err := client.JSONRPCCall(network.URL, "eth_call", testCase.params...) + require.NoError(t, err) + require.NotNil(t, response.Error) + require.Nil(t, response.Result) + require.Equal(t, testCase.expectedError.Code, response.Error.Code) + require.Equal(t, testCase.expectedError.Message, response.Error.Message) + }) + } + } +} diff --git a/test/e2e/jsonrpc_test.go b/test/e2e/jsonrpc_test.go deleted file mode 100644 index 1e12178324..0000000000 --- a/test/e2e/jsonrpc_test.go +++ /dev/null @@ -1,186 +0,0 @@ -package e2e - -import ( - "bytes" - "context" - "fmt" - "io/ioutil" - "math/big" - "net/http" - "strings" - "testing" - - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/stretchr/testify/require" -) - -// TestJSONRPC tests JSON RPC methods on a running environment. -func TestJSONRPC(t *testing.T) { - if testing.Short() { - t.Skip() - } - - ctx := context.Background() - - opsCfg := &operations.Config{ - State: &state.Config{MaxCumulativeGasUsed: operations.DefaultMaxCumulativeGasUsed}, - Sequencer: &operations.SequencerConfig{Address: operations.DefaultSequencerAddress, PrivateKey: operations.DefaultSequencerPrivateKey}, - } - opsman, err := operations.NewManager(ctx, opsCfg) - require.NoError(t, err) - - defer func() { - require.NoError(t, operations.Teardown()) - }() - - sequencerBalance := new(big.Int).SetInt64(int64(operations.DefaultSequencerBalance)) - - genesisAccounts := make(map[string]big.Int) - genesisAccounts[operations.DefaultSequencerAddress] = *sequencerBalance - require.NoError(t, opsman.SetGenesis(genesisAccounts)) - - require.NoError(t, opsman.Setup()) - - require.NoError(t, deployContracts(opsman)) - - tcs := []struct { - description, input, expectedOutput string - expectedErr bool - expectedErrMsg string - }{ - { - description: "eth_call, calling double(int256) with data 5", - input: `{"jsonrpc":"2.0", "method":"eth_call", "params":[{"from": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "to": "0x1275fbb540c8efC58b812ba83B0D0B8b9917AE98", "data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"}, "latest"], "id":1}`, - expectedOutput: `{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000000a"}`, - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - actualOutput, err := httpQuery(tc.input) - if err := checkError(err, tc.expectedErr, tc.expectedErrMsg); err != nil { - t.Fatalf(err.Error()) - } - - if actualOutput != tc.expectedOutput { - t.Fatalf("Query return value did not match expectation, got %q, want %q", actualOutput, tc.expectedOutput) - } - }) - } -} - -func httpQuery(payload string) (string, error) { - const target = "http://localhost:8123" - - var jsonStr = []byte(payload) - req, err := http.NewRequest( - "POST", target, - bytes.NewBuffer(jsonStr)) - if err != nil { - return "", err - } - - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - res, err := client.Do(req) - if err != nil { - return "", err - } - - if res.Body != nil { - defer func() { - err = res.Body.Close() - }() - } - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return "", err - } - - return string(body), nil -} - -func checkError(err error, expected bool, msg string) error { - if !expected && err != nil { - return fmt.Errorf("Unexpected error %v", err) - } - if !expected { - return nil - } - if err == nil { - return fmt.Errorf("Expected error didn't happen") - } - if msg == "" { - return fmt.Errorf("Expected error message not defined") - } - if !strings.HasPrefix(err.Error(), msg) { - return fmt.Errorf("Wrong error, expected %q, got %q", msg, err.Error()) - } - return nil -} - -func deployContracts(opsman *operations.Manager) error { - panic("not implemented yet") - // var txs []*types.Transaction - - // bytecode, err := testutils.ReadBytecode("Double/Double.bin") - // if err != nil { - // return err - // } - // tx0 := types.NewTx(&types.LegacyTx{ - // Nonce: 0, - // To: nil, - // Value: new(big.Int), - // Gas: uint64(defaultSequencerBalance), - // GasPrice: new(big.Int).SetUint64(1), - // Data: common.Hex2Bytes(bytecode), - // }) - - // auth, err := operations.GetAuth( - // defaultSequencerPrivateKey, - // new(big.Int).SetInt64(defaultSequencerChainID)) - // if err != nil { - // return err - // } - // signedTx0, err := auth.Signer(auth.From, tx0) - // if err != nil { - // return err - // } - // txs = append(txs, signedTx0) - - // // Create Batch - // sequencerAddress := common.HexToAddress(defaultSequencerAddress) - // batch := &state.Batch{ - // BlockNumber: uint64(0), - // Sequencer: sequencerAddress, - // Aggregator: sequencerAddress, - // ConsolidatedTxHash: common.Hash{}, - // Header: &types.Header{Number: big.NewInt(0).SetUint64(1)}, - // Uncles: nil, - // Transactions: txs, - // RawTxsData: nil, - // MaticCollateral: big.NewInt(1), - // ReceivedAt: time.Now(), - // ChainID: big.NewInt(defaultSequencerChainID), - // GlobalExitRoot: common.HexToHash("0x29e885edaf8e4b51e1d2e05f9da28161d2fb4f6b1d53827d9b80a23cf2d7d9fc"), - // } - - // st := opsman.State() - // ctx := context.Background() - - // lastVirtualBatch, err := st.GetLastBatch(ctx, true, "") - // if err != nil { - // return err - // } - - // bp, err := st.NewBatchProcessor(ctx, sequencerAddress, lastVirtualBatch.Header.Root[:], "") - // if err != nil { - // return err - // } - - // return bp.ProcessBatch(ctx, batch) -} diff --git a/test/e2e/permissionlessrpc_test.go b/test/e2e/permissionlessrpc_test.go new file mode 100644 index 0000000000..c984bf69de --- /dev/null +++ b/test/e2e/permissionlessrpc_test.go @@ -0,0 +1,130 @@ +package e2e + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func TestPermissionlessJRPC(t *testing.T) { + // Initial setup: + // - permissionless RPC + Sync + // - trusted node with everything minus EthTxMan (to prevent the trusted state from being virtualized) + if testing.Short() { + t.Skip() + } + ctx := context.Background() + defer func() { require.NoError(t, operations.TeardownPermissionless()) }() + err := operations.Teardown() + require.NoError(t, err) + opsCfg := operations.GetDefaultOperationsConfig() + opsCfg.State.MaxCumulativeGasUsed = 80000000000 + opsman, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + require.NoError(t, opsman.SetupWithPermissionless()) + require.NoError(t, opsman.StopEthTxSender()) + time.Sleep(5 * time.Second) + + // Step 1: + // - actions: send nTxsStep1 transactions to the trusted sequencer through the permissionless sequencer + // first transaction gets the current nonce. The others are generated + // - assert: transactions are properly relayed, added in to the trusted state and broadcasted to the permissionless node + + nTxsStep1 := 10 + // Load account with balance on local genesis + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) + require.NoError(t, err) + // Load eth client (permissionless RPC) + client, err := ethclient.Dial(operations.PermissionlessL2NetworkURL) + require.NoError(t, err) + // Send txs + amount := big.NewInt(10000) + toAddress := common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8") + senderBalance, err := client.BalanceAt(ctx, auth.From, nil) + require.NoError(t, err) + nonceToBeUsedForNextTx, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + log.Infof("Receiver Addr: %v", toAddress.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", nonceToBeUsedForNextTx) + + gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &toAddress, Value: amount}) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + txsStep1 := make([]*types.Transaction, 0, nTxsStep1) + for i := 0; i < nTxsStep1; i++ { + tx := types.NewTransaction(nonceToBeUsedForNextTx, toAddress, amount, gasLimit, gasPrice, nil) + txsStep1 = append(txsStep1, tx) + nonceToBeUsedForNextTx += 1 + } + log.Infof("sending %d txs and waiting until added in the permissionless RPC trusted state") + l2BlockNumbersStep1, err := operations.ApplyL2Txs(ctx, txsStep1, auth, client, operations.TrustedConfirmationLevel) + require.NoError(t, err) + + // Step 2 + // - actions: stop the sequencer and send nTxsStep2 transactions, then use the getPendingNonce, and send tx with the resulting nonce + // - assert: pendingNonce works as expected (force a scenario where the pool needs to be taken into consideration) + nTxsStep2 := 10 + require.NoError(t, opsman.StopSequencer()) + require.NoError(t, opsman.StopSequenceSender()) + txsStep2 := make([]*types.Transaction, 0, nTxsStep2) + for i := 0; i < nTxsStep2; i++ { + tx := types.NewTransaction(nonceToBeUsedForNextTx, toAddress, amount, gasLimit, gasPrice, nil) + txsStep2 = append(txsStep2, tx) + nonceToBeUsedForNextTx += 1 + } + log.Infof("sending %d txs and waiting until added into the trusted sequencer pool") + _, err = operations.ApplyL2Txs(ctx, txsStep2, auth, client, operations.PoolConfirmationLevel) + require.NoError(t, err) + actualNonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + require.Equal(t, nonceToBeUsedForNextTx, actualNonce) + // Step 3 + // - actions: start Sequencer and EthTxSender + // - assert: all transactions get virtualized WITHOUT L2 reorgs + require.NoError(t, opsman.StartSequencer()) + require.NoError(t, opsman.StartEthTxSender()) + require.NoError(t, opsman.StartSequenceSender()) + + lastL2BlockNumberStep1 := l2BlockNumbersStep1[len(l2BlockNumbersStep1)-1] + lastL2BlockNumberStep2 := lastL2BlockNumberStep1.Add( + lastL2BlockNumberStep1, + big.NewInt(int64(nTxsStep2)), + ) + err = operations.WaitL2BlockToBeVirtualizedCustomRPC( + lastL2BlockNumberStep2, 4*time.Minute, //nolint:gomnd + operations.PermissionlessL2NetworkURL, + ) + require.NoError(t, err) + sqlDB, err := db.NewSQLDB(db.Config{ + User: testutils.GetEnv("PERMISSIONLESSPGUSER", "test_user"), + Password: testutils.GetEnv("PERMISSIONLESSPGPASSWORD", "test_password"), + Name: testutils.GetEnv("PERMISSIONLESSPGDATABASE", "state_db"), + Host: testutils.GetEnv("PERMISSIONLESSPGHOST", "localhost"), + Port: testutils.GetEnv("PERMISSIONLESSPGPORT", "5434"), + EnableLog: true, + MaxConns: 4, + }) + require.NoError(t, err) + const isThereL2ReorgQuery = "SELECT COUNT(*) > 0 FROM state.trusted_reorg;" + row := sqlDB.QueryRow(context.Background(), isThereL2ReorgQuery) + isThereL2Reorg := true + require.NoError(t, row.Scan(&isThereL2Reorg)) + require.False(t, isThereL2Reorg) +} diff --git a/test/e2e/pool_test.go b/test/e2e/pool_test.go index 5f5f6ebea7..ded7a5d0d5 100644 --- a/test/e2e/pool_test.go +++ b/test/e2e/pool_test.go @@ -69,7 +69,7 @@ func TestRepeatedNonce(t *testing.T) { require.Equal(t, "replacement transaction underpriced", err.Error()) log.Debug("waiting correct nonce tx to be mined") - err = operations.WaitTxToBeMined(client, correctNonceSignedTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, correctNonceSignedTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) } } @@ -126,7 +126,7 @@ func TestRepeatedTx(t *testing.T) { require.Equal(t, "already known", err.Error()) log.Debug("waiting correct nonce tx to be mined") - err = operations.WaitTxToBeMined(client, signedTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, signedTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) } } diff --git a/test/e2e/preEIP155_test.go b/test/e2e/preEIP155_test.go new file mode 100644 index 0000000000..57ce1a536f --- /dev/null +++ b/test/e2e/preEIP155_test.go @@ -0,0 +1,90 @@ +package e2e + +import ( + "context" + "strings" + "testing" + "time" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "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/stretchr/testify/require" +) + +func TestPreEIP155Tx(t *testing.T) { + if testing.Short() { + t.Skip() + } + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { + require.NoError(t, operations.Teardown()) + }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + for _, network := range networks { + log.Debugf(network.Name) + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + nonce, err := client.PendingNonceAt(ctx, auth.From) + require.NoError(t, err) + + gasPrice, err := client.SuggestGasPrice(ctx) + require.NoError(t, err) + + to := common.HexToAddress("0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98") + data := hex.DecodeBig("0x64fbb77c").Bytes() + + gas, err := client.EstimateGas(ctx, ethereum.CallMsg{ + From: auth.From, + To: &to, + Data: data, + }) + require.NoError(t, err) + + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: &to, + GasPrice: gasPrice, + Gas: gas, + Data: data, + }) + + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(network.PrivateKey, "0x")) + require.NoError(t, err) + + signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, privateKey) + require.NoError(t, err) + + err = client.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + err = operations.WaitTxToBeMined(ctx, client, signedTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + receipt, err := client.TransactionReceipt(ctx, signedTx.Hash()) + require.NoError(t, err) + + // wait for l2 block to be virtualized + if network.ChainID == operations.DefaultL2ChainID { + log.Infof("waiting for the block number %v to be virtualized", receipt.BlockNumber.String()) + err = operations.WaitL2BlockToBeVirtualized(receipt.BlockNumber, 4*time.Minute) //nolint:gomnd + require.NoError(t, err) + } + } +} diff --git a/test/e2e/sc_test.go b/test/e2e/sc_test.go index a8e6f36e3c..a6fb0f7f73 100644 --- a/test/e2e/sc_test.go +++ b/test/e2e/sc_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Counter" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/EmitLog2" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/FailureTest" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Read" @@ -17,6 +18,54 @@ import ( "github.com/stretchr/testify/require" ) +func TestCounter(t *testing.T) { + if testing.Short() { + t.Skip() + } + + var err error + err = operations.Teardown() + require.NoError(t, err) + + defer func() { require.NoError(t, operations.Teardown()) }() + + ctx := context.Background() + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + require.NoError(t, err) + err = opsMan.Setup() + require.NoError(t, err) + + for _, network := range networks { + log.Debugf(network.Name) + client := operations.MustGetClient(network.URL) + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + + _, scTx, sc, err := Counter.DeployCounter(auth, client) + require.NoError(t, err) + + logTx(scTx) + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + count, err := sc.GetCount(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + + assert.Equal(t, 0, count.Cmp(big.NewInt(0))) + + scCallTx, err := sc.Increment(auth) + require.NoError(t, err) + + logTx(scCallTx) + err = operations.WaitTxToBeMined(ctx, client, scCallTx, operations.DefaultTimeoutTxToBeMined) + require.NoError(t, err) + + count, err = sc.GetCount(&bind.CallOpts{Pending: false}) + require.NoError(t, err) + assert.Equal(t, 0, count.Cmp(big.NewInt(1))) + } +} + func TestEmitLog2(t *testing.T) { if testing.Short() { t.Skip() @@ -44,14 +93,14 @@ func TestEmitLog2(t *testing.T) { require.NoError(t, err) logTx(scTx) - err = operations.WaitTxToBeMined(client, scTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) scCallTx, err := sc.EmitLogs(auth) require.NoError(t, err) logTx(scCallTx) - err = operations.WaitTxToBeMined(client, scCallTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, scCallTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) scCallTxReceipt, err := client.TransactionReceipt(ctx, scCallTx.Hash()) @@ -63,14 +112,19 @@ func TestEmitLog2(t *testing.T) { Addresses: []common.Address{scAddr}, }) require.NoError(t, err) - assert.Equal(t, 3, len(logs)) + assert.Equal(t, 4, len(logs)) + + log0 := logs[0] + assert.Equal(t, 0, len(log0.Topics)) - _, err = sc.ParseLog(logs[0]) + _, err = sc.ParseLog(logs[1]) require.NoError(t, err) - logA, err := sc.ParseLogA(logs[1]) + + logA, err := sc.ParseLogA(logs[2]) require.NoError(t, err) assert.Equal(t, big.NewInt(1), logA.A) - logABCD, err := sc.ParseLogABCD(logs[2]) + + logABCD, err := sc.ParseLogABCD(logs[3]) require.NoError(t, err) assert.Equal(t, big.NewInt(1), logABCD.A) assert.Equal(t, big.NewInt(2), logABCD.B) @@ -107,7 +161,7 @@ func TestFailureTest(t *testing.T) { require.NoError(t, err) logTx(scTx) - err = operations.WaitTxToBeMined(client, scTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) log.Debug("storing value") @@ -115,7 +169,7 @@ func TestFailureTest(t *testing.T) { require.NoError(t, err) logTx(scCallTx) - err = operations.WaitTxToBeMined(client, scCallTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, scCallTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) log.Debug("storing value with revert") @@ -155,7 +209,7 @@ func TestRead(t *testing.T) { require.NoError(t, err) logTx(scTx) - err = operations.WaitTxToBeMined(client, scTx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, scTx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) log.Debug("read string public variable directly") @@ -184,14 +238,14 @@ func TestRead(t *testing.T) { tx, err := sc.PublicAddToken(auth, tA) require.NoError(t, err) logTx(tx) - err = operations.WaitTxToBeMined(client, tx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) log.Debug("external add token") tx, err = sc.ExternalAddToken(auth, tB) require.NoError(t, err) logTx(tx) - err = operations.WaitTxToBeMined(client, tx.Hash(), operations.DefaultTimeoutTxToBeMined) + err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined) require.NoError(t, err) log.Debug("read mapping public variable directly") diff --git a/test/e2e/shared.go b/test/e2e/shared.go index 09b0c09f6a..9e464d7dd1 100644 --- a/test/e2e/shared.go +++ b/test/e2e/shared.go @@ -1,23 +1,113 @@ +//nolint:deadcode,unused,varcheck package e2e import ( + "context" + "fmt" + "math/big" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +const ( + invalidParamsErrorCode = -32602 + toAddressHex = "0x4d5Cf5032B2a844602278b01199ED191A86c93ff" + gerFinalityBlocks = uint64(250) +) + +var ( + toAddress = common.HexToAddress(toAddressHex) ) var networks = []struct { - Name string - URL string - ChainID uint64 - PrivateKey string + Name string + URL string + WebSocketURL string + ChainID uint64 + PrivateKey string }{ - {Name: "Local L1", URL: operations.DefaultL1NetworkURL, ChainID: operations.DefaultL1ChainID, PrivateKey: operations.DefaultSequencerPrivateKey}, - {Name: "Local L2", URL: operations.DefaultL2NetworkURL, ChainID: operations.DefaultL2ChainID, PrivateKey: operations.DefaultSequencerPrivateKey}, + { + Name: "Local L1", + URL: operations.DefaultL1NetworkURL, + WebSocketURL: operations.DefaultL1NetworkWebSocketURL, + ChainID: operations.DefaultL1ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, + { + Name: "Local L2", + URL: operations.DefaultL2NetworkURL, + WebSocketURL: operations.DefaultL2NetworkWebSocketURL, + ChainID: operations.DefaultL2ChainID, + PrivateKey: operations.DefaultSequencerPrivateKey, + }, +} + +func setup() { + var err error + ctx := context.Background() + err = operations.Teardown() + if err != nil { + panic(err) + } + + opsCfg := operations.GetDefaultOperationsConfig() + opsMan, err := operations.NewManager(ctx, opsCfg) + if err != nil { + panic(err) + } + err = opsMan.Setup() + if err != nil { + panic(err) + } +} + +func teardown() { + err := operations.Teardown() + if err != nil { + panic(err) + } +} + +func createTX(client *ethclient.Client, auth *bind.TransactOpts, to common.Address, amount *big.Int) (*ethTypes.Transaction, error) { + nonce, err := client.NonceAt(context.Background(), auth.From, nil) + if err != nil { + return nil, err + } + gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{From: auth.From, To: &to, Value: amount}) + if err != nil { + return nil, err + } + + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + return nil, err + } + + log.Infof("\nTX details:\n\tNonce: %d\n\tGasLimit: %d\n\tGasPrice: %d", nonce, gasLimit, gasPrice) + if gasLimit != uint64(21000) { //nolint:gomnd + return nil, fmt.Errorf("gasLimit %d != 21000", gasLimit) + } + tx := ethTypes.NewTransaction(nonce, to, amount, gasLimit, gasPrice, nil) + signedTx, err := auth.Signer(auth.From, tx) + if err != nil { + return nil, err + } + log.Infof("Sending Tx %v Nonce %v", signedTx.Hash(), signedTx.Nonce()) + err = client.SendTransaction(context.Background(), signedTx) + if err != nil { + return nil, err + } + return signedTx, nil } -func logTx(tx *types.Transaction) { +func logTx(tx *ethTypes.Transaction) { sender, _ := state.GetSender(*tx) log.Debugf("********************") log.Debugf("Hash: %v", tx.Hash()) diff --git a/test/e2e/state_test.go b/test/e2e/state_test.go index 3261f0b153..38dabedb34 100644 --- a/test/e2e/state_test.go +++ b/test/e2e/state_test.go @@ -12,6 +12,8 @@ import ( "github.com/0xPolygonHermez/zkevm-node/test/operations" "github.com/0xPolygonHermez/zkevm-node/test/vectors" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/require" ) @@ -37,9 +39,12 @@ func TestStateTransition(t *testing.T) { State: &state.Config{ MaxCumulativeGasUsed: 800000, }, - Sequencer: &operations.SequencerConfig{ - Address: testCase.SequencerAddress, - PrivateKey: testCase.SequencerPrivateKey, + SequenceSender: &operations.SequenceSenderConfig{ + SenderAddress: testCase.SequencerAddress, + LastBatchVirtualizationTimeMaxWaitPeriod: "5s", + WaitPeriodSendSequence: "5s", + MaxTxSizeForL1: 131072, + PrivateKey: testCase.SequencerPrivateKey, }, } opsman, err := operations.NewManager(ctx, opsCfg) @@ -49,28 +54,40 @@ func TestStateTransition(t *testing.T) { for _, gacc := range testCase.GenesisAccounts { genesisAccounts[gacc.Address] = gacc.Balance.Int } - require.NoError(t, opsman.SetGenesis(genesisAccounts)) + require.NoError(t, opsman.SetGenesisAccountsBalance(genesisAccounts)) // Check initial root require.NoError(t, opsman.CheckVirtualRoot(testCase.ExpectedOldRoot)) require.NoError(t, opsman.Setup()) - require.NoError(t, opsman.ApplyTxs(testCase.Txs, testCase.ExpectedOldRoot, testCase.ExpectedNewRoot, testCase.GlobalExitRoot)) + // convert vector txs + txs := make([]*types.Transaction, 0, len(testCase.Txs)) + for i := 0; i < len(testCase.Txs); i++ { + vecTx := testCase.Txs[i] + var tx types.Transaction + err := rlp.DecodeBytes([]byte(vecTx.RawTx), &tx) + require.NoError(t, err) + txs = append(txs, &tx) + } + + // send transactions + _, err = operations.ApplyL2Txs(ctx, txs, nil, nil, operations.VerifiedConfirmationLevel) + require.NoError(t, err) st := opsman.State() // Check leafs - l2BlockNumber, err := st.GetLastL2BlockNumber(ctx, nil) + l2Block, err := st.GetLastL2Block(ctx, nil) require.NoError(t, err) for addrStr, leaf := range testCase.ExpectedNewLeafs { addr := common.HexToAddress(addrStr) - actualBalance, err := st.GetBalance(ctx, addr, l2BlockNumber, nil) + actualBalance, err := st.GetBalance(ctx, addr, l2Block.Root()) require.NoError(t, err) require.Equal(t, 0, leaf.Balance.Cmp(actualBalance), fmt.Sprintf("addr: %s expected: %s found: %s", addr.Hex(), leaf.Balance.Text(encoding.Base10), actualBalance.Text(encoding.Base10))) - actualNonce, err := st.GetNonce(ctx, addr, l2BlockNumber, nil) + actualNonce, err := st.GetNonce(ctx, addr, l2Block.Root()) require.NoError(t, err) require.Equal(t, leaf.Nonce, strconv.FormatUint(actualNonce, encoding.Base10), fmt.Sprintf("addr: %s expected: %s found: %d", addr.Hex(), leaf.Nonce, actualNonce)) } diff --git a/test/e2e/uniswap_test.go b/test/e2e/uniswap_test.go index 9c8fb02400..409d7775ff 100644 --- a/test/e2e/uniswap_test.go +++ b/test/e2e/uniswap_test.go @@ -38,16 +38,18 @@ func TestUniswap(t *testing.T) { State: &state.Config{ MaxCumulativeGasUsed: cfg.Sequencer.MaxCumulativeGasUsed, }, - Sequencer: &operations.SequencerConfig{ - Address: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - PrivateKey: "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + SequenceSender: &operations.SequenceSenderConfig{ + SenderAddress: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + LastBatchVirtualizationTimeMaxWaitPeriod: "5s", + WaitPeriodSendSequence: "5s", + MaxTxSizeForL1: 131072, + PrivateKey: "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", }, } opsman, err := operations.NewManager(ctx, opsCfg) require.NoError(t, err) require.NoError(t, opsman.StartNetwork()) - require.NoError(t, opsman.SetUpSequencer()) require.NoError(t, opsman.StartNode()) require.NoError(t, opsman.InitNetwork()) diff --git a/test/operations/manager.go b/test/operations/manager.go index 4ec92d6cd2..4f3a7ca83e 100644 --- a/test/operations/manager.go +++ b/test/operations/manager.go @@ -6,66 +6,76 @@ import ( "math/big" "os" "os/exec" + "path/filepath" "strings" "time" "github.com/0xPolygonHermez/zkevm-node/db" - "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/event" + "github.com/0xPolygonHermez/zkevm-node/event/nileventstorage" + "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/merkletree" "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor" + "github.com/0xPolygonHermez/zkevm-node/test/constants" "github.com/0xPolygonHermez/zkevm-node/test/dbutils" - "github.com/0xPolygonHermez/zkevm-node/test/vectors" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" "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" ) const ( - executorURI = "127.0.0.1:50071" - merkletreeURI = "127.0.0.1:50061" - - poeAddress = "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" - maticTokenAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3" //nolint:gosec - - l1AccHexAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - l1AccHexPrivateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + cmdFolder = "test" ) -// Public constants +// Public shared const ( - DefaultSequencerAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - DefaultSequencerPrivateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" - DefaultSequencerBalance = 400000 - DefaultMaxCumulativeGasUsed = 800000 - - DefaultL1NetworkURL = "http://localhost:8545" - DefaultL1ChainID uint64 = 1337 - DefaultL2NetworkURL = "http://localhost:8123" - DefaultL2ChainID uint64 = 1001 + DefaultSequencerAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + DefaultSequencerPrivateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + DefaultSequencerBalance = 400000 + DefaultMaxCumulativeGasUsed = 800000 + DefaultL1ZkEVMSmartContract = "0x610178dA211FEF7D417bC0e6FeD39F05609AD788" + DefaultL1NetworkURL = "http://localhost:8545" + DefaultL1NetworkWebSocketURL = "ws://localhost:8546" + DefaultL1ChainID uint64 = 1337 + + DefaultL2NetworkURL = "http://localhost:8123" + PermissionlessL2NetworkURL = "http://localhost:8125" + DefaultL2NetworkWebSocketURL = "ws://localhost:8133" + DefaultL2ChainID uint64 = 1001 DefaultTimeoutTxToBeMined = 1 * time.Minute + + DefaultWaitPeriodSendSequence = "15s" + DefaultLastBatchVirtualizationTimeMaxWaitPeriod = "10s" + DefaultMaxTxSizeForL1 uint64 = 131072 ) var ( - stateDBCfg = dbutils.NewStateConfigFromEnv() - poolDBCfg = dbutils.NewPoolConfigFromEnv() - rpcDBCfg = dbutils.NewRPCConfigFromEnv() + stateDBCfg = dbutils.NewStateConfigFromEnv() + poolDBCfg = dbutils.NewPoolConfigFromEnv() + + executorURI = testutils.GetEnv(constants.ENV_ZKPROVER_URI, "127.0.0.1:50071") + merkleTreeURI = testutils.GetEnv(constants.ENV_MERKLETREE_URI, "127.0.0.1:50061") executorConfig = executor.Config{URI: executorURI} - merkletreeConfig = merkletree.Config{URI: merkletreeURI} + merkleTreeConfig = merkletree.Config{URI: merkleTreeURI} ) -// SequencerConfig is the configuration for the sequencer operations. -type SequencerConfig struct { - Address, PrivateKey string +// SequenceSenderConfig is the configuration for the sequence sender operations +type SequenceSenderConfig struct { + WaitPeriodSendSequence string + LastBatchVirtualizationTimeMaxWaitPeriod string + MaxTxSizeForL1 uint64 + SenderAddress string + PrivateKey string } // Config is the main Manager configuration. type Config struct { - State *state.Config - Sequencer *SequencerConfig + State *state.Config + SequenceSender *SequenceSenderConfig } // Manager controls operations and has knowledge about how to set up and tear @@ -125,8 +135,22 @@ func (m *Manager) CheckConsolidatedRoot(expectedRoot string) error { // return m.checkRoot(root, expectedRoot) } -// SetGenesis creates the genesis block in the state. -func (m *Manager) SetGenesis(genesisAccounts map[string]big.Int) error { +// SetGenesisAccountsBalance creates the genesis block in the state. +func (m *Manager) SetGenesisAccountsBalance(genesisAccounts map[string]big.Int) error { + var genesisActions []*state.GenesisAction + for address, balanceValue := range genesisAccounts { + action := &state.GenesisAction{ + Address: address, + Type: int(merkletree.LeafTypeBalance), + Value: balanceValue.String(), + } + genesisActions = append(genesisActions, action) + } + + return m.SetGenesis(genesisActions) +} + +func (m *Manager) SetGenesis(genesisActions []*state.GenesisAction) error { genesisBlock := state.Block{ BlockNumber: 0, BlockHash: state.ZeroHash, @@ -134,15 +158,7 @@ func (m *Manager) SetGenesis(genesisAccounts map[string]big.Int) error { ReceivedAt: time.Now(), } genesis := state.Genesis{ - Actions: []*state.GenesisAction{}, - } - for address, balanceValue := range genesisAccounts { - action := &state.GenesisAction{ - Address: address, - Type: int(merkletree.LeafTypeBalance), - Value: balanceValue.String(), - } - genesis.Actions = append(genesis.Actions, action) + GenesisActions: genesisActions, } dbTx, err := m.st.BeginStateTransaction(m.ctx) @@ -152,79 +168,139 @@ func (m *Manager) SetGenesis(genesisAccounts map[string]big.Int) error { _, err = m.st.SetGenesis(m.ctx, genesisBlock, genesis, dbTx) + err = dbTx.Commit(m.ctx) + if err != nil { + return err + } + return err } -// ApplyTxs sends the given L2 txs, waits for them to be consolidated and checks -// the final state. -func (m *Manager) ApplyTxs(vectorTxs []vectors.Tx, initialRoot, finalRoot, globalExitRoot string) error { - panic("not implemented yet") - // // store current batch number to check later when the state is updated - // currentBatchNumber, err := m.st.GetLastBatchNumberSeenOnEthereum(m.ctx, nil) - // if err != nil { - // return err - // } +// ApplyL1Txs sends the given L1 txs, waits for them to be consolidated and +// checks the final state. +func ApplyL1Txs(ctx context.Context, txs []*types.Transaction, auth *bind.TransactOpts, client *ethclient.Client) error { + _, err := applyTxs(ctx, txs, auth, client, true) + return err +} - // var txs []*types.Transaction - // for _, vectorTx := range vectorTxs { - // if string(vectorTx.RawTx) != "" && vectorTx.Overwrite.S == "" { - // var tx types.LegacyTx - // bytes, err := hex.DecodeHex(vectorTx.RawTx) - // if err != nil { - // return err - // } - - // err = rlp.DecodeBytes(bytes, &tx) - // if err == nil { - // txs = append(txs, types.NewTx(&tx)) - // } - // if err != nil { - // return err - // } - // } - // } - // // Create Batch - // batch := &state.Batch{ - // BlockNumber: uint64(0), - // Sequencer: common.HexToAddress(m.cfg.Sequencer.Address), - // Aggregator: common.HexToAddress(aggregatorAddress), - // ConsolidatedTxHash: common.Hash{}, - // Header: &types.Header{Number: big.NewInt(0).SetUint64(1)}, - // Uncles: nil, - // Transactions: txs, - // RawTxsData: nil, - // MaticCollateral: big.NewInt(1), - // ChainID: big.NewInt(int64(m.cfg.NetworkConfig.ChainID)), - // GlobalExitRoot: common.HexToHash(globalExitRoot), - // } +// ConfirmationLevel type used to describe the confirmation level of a transaction +type ConfirmationLevel int - // // Create Batch Processor - // bp, err := m.st.NewBatchProcessor(m.ctx, common.HexToAddress(m.cfg.Sequencer.Address), common.Hex2Bytes(strings.TrimPrefix(initialRoot, "0x")), "") - // if err != nil { - // return err - // } +// PoolConfirmationLevel indicates that transaction is added into the pool +const PoolConfirmationLevel ConfirmationLevel = 0 - // err = bp.ProcessBatch(m.ctx, batch) - // if err != nil { - // return err - // } +// TrustedConfirmationLevel indicates that transaction is added into the trusted state +const TrustedConfirmationLevel ConfirmationLevel = 1 - // // Wait for sequencer to select txs from pool and propose a new batch - // // Wait for the synchronizer to update state - // err = Poll(DefaultInterval, DefaultDeadline, func() (bool, error) { - // // using a closure here to capture st and currentBatchNumber - // latestBatchNumber, err := m.st.GetLastBatchNumberConsolidatedOnEthereum(m.ctx, "") - // if err != nil { - // return false, err - // } - // done := latestBatchNumber > currentBatchNumber - // return done, nil - // }) - // // if the state is not expected to change waitPoll can timeout - // if initialRoot != "" && finalRoot != "" && initialRoot != finalRoot && err != nil { - // return err - // } - // return nil +// VirtualConfirmationLevel indicates that transaction is added into the virtual state +const VirtualConfirmationLevel ConfirmationLevel = 2 + +// VerifiedConfirmationLevel indicates that transaction is added into the verified state +const VerifiedConfirmationLevel ConfirmationLevel = 3 + +// ApplyL2Txs sends the given L2 txs, waits for them to be consolidated and +// checks the final state. +func ApplyL2Txs(ctx context.Context, txs []*types.Transaction, auth *bind.TransactOpts, client *ethclient.Client, confirmationLevel ConfirmationLevel) ([]*big.Int, error) { + var err error + if auth == nil { + auth, err = GetAuth(DefaultSequencerPrivateKey, DefaultL2ChainID) + if err != nil { + return nil, err + } + } + + if client == nil { + client, err = ethclient.Dial(DefaultL2NetworkURL) + if err != nil { + return nil, err + } + } + waitToBeMined := confirmationLevel != PoolConfirmationLevel + sentTxs, err := applyTxs(ctx, txs, auth, client, waitToBeMined) + if err != nil { + return nil, err + } + if confirmationLevel == PoolConfirmationLevel { + return nil, nil + } + + l2BlockNumbers := make([]*big.Int, 0, len(sentTxs)) + for _, tx := range sentTxs { + // check transaction nonce against transaction reported L2 block number + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) + if err != nil { + return nil, err + } + + // get L2 block number + l2BlockNumbers = append(l2BlockNumbers, receipt.BlockNumber) + expectedNonce := receipt.BlockNumber.Uint64() - 1 + 8 //nolint:gomnd + if tx.Nonce() != expectedNonce { + return nil, fmt.Errorf("mismatching nonce for tx %v: want %d, got %d\n", tx.Hash(), expectedNonce, tx.Nonce()) + } + if confirmationLevel == TrustedConfirmationLevel { + continue + } + + // wait for l2 block to be virtualized + log.Infof("waiting for the block number %v to be virtualized", receipt.BlockNumber.String()) + err = WaitL2BlockToBeVirtualized(receipt.BlockNumber, 4*time.Minute) //nolint:gomnd + if err != nil { + return nil, err + } + if confirmationLevel == VirtualConfirmationLevel { + continue + } + + // wait for l2 block number to be consolidated + log.Infof("waiting for the block number %v to be consolidated", receipt.BlockNumber.String()) + err = WaitL2BlockToBeConsolidated(receipt.BlockNumber, 4*time.Minute) //nolint:gomnd + if err != nil { + return nil, err + } + } + + return l2BlockNumbers, nil +} + +func applyTxs(ctx context.Context, txs []*types.Transaction, auth *bind.TransactOpts, client *ethclient.Client, waitToBeMined bool) ([]*types.Transaction, error) { + var sentTxs []*types.Transaction + + for i := 0; i < len(txs); i++ { + signedTx, err := auth.Signer(auth.From, txs[i]) + if err != nil { + return nil, err + } + log.Infof("Sending Tx %v Nonce %v", signedTx.Hash(), signedTx.Nonce()) + err = client.SendTransaction(context.Background(), signedTx) + if err != nil { + return nil, err + } + + sentTxs = append(sentTxs, signedTx) + } + if !waitToBeMined { + return nil, nil + } + + // wait for TX to be mined + timeout := 180 * time.Second //nolint:gomnd + for _, tx := range sentTxs { + log.Infof("Waiting Tx %s to be mined", tx.Hash()) + err := WaitTxToBeMined(ctx, client, tx, timeout) + if err != nil { + return nil, err + } + log.Infof("Tx %s mined successfully", tx.Hash()) + } + nTxs := len(txs) + if nTxs > 1 { + log.Infof("%d transactions added into the trusted state successfully.", nTxs) + } else { + log.Info("transaction added into the trusted state successfully.") + } + + return sentTxs, nil } // GetAuth configures and returns an auth object. @@ -256,168 +332,128 @@ func (m *Manager) Setup() error { } // Approve matic - err = approveMatic() + err = ApproveMatic() if err != nil { return err } - err = m.SetUpSequencer() + // Run node container + err = m.StartNode() if err != nil { return err } - // Run node container - return m.StartNode() + return nil } -// Teardown stops all the components. -func Teardown() error { - err := stopNode() +// SetupWithPermissionless creates all the required components for both trusted and permissionless nodes +// and initializes them according to the manager config. +func (m *Manager) SetupWithPermissionless() error { + // Run network container + err := m.StartNetwork() if err != nil { return err } - err = stopNetwork() + // Approve matic + err = ApproveMatic() if err != nil { return err } - return nil -} - -func initState(maxCumulativeGasUsed uint64) (*state.State, error) { - sqlDB, err := db.NewSQLDB(stateDBCfg) + err = m.StartTrustedAndPermissionlessNode() if err != nil { - return nil, err - } - - ctx := context.Background() - stateDb := state.NewPostgresStorage(sqlDB) - executorClient, _, _ := executor.NewExecutorClient(ctx, executorConfig) - stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, merkletreeConfig) - stateTree := merkletree.NewStateTree(stateDBClient) - - stateCfg := state.Config{ - MaxCumulativeGasUsed: maxCumulativeGasUsed, + return err } - st := state.NewState(stateCfg, stateDb, executorClient, stateTree) - return st, nil + // Run node container + return nil } -// func (m *Manager) checkRoot(root []byte, expectedRoot string) error { -// actualRoot := hex.EncodeToHex(root) - -// if expectedRoot != actualRoot { -// return fmt.Errorf("Invalid root, want %q, got %q", expectedRoot, actualRoot) -// } -// return nil -// } +// StartEthTxSender stops the eth tx sender service +func (m *Manager) StartEthTxSender() error { + return StartComponent("eth-tx-manager") +} -// SetUpSequencer provide ETH, Matic to and register the sequencer -func (m *Manager) SetUpSequencer() error { - // Eth client - client, err := ethclient.Dial(DefaultL1NetworkURL) - if err != nil { - return err - } +// StopEthTxSender stops the eth tx sender service +func (m *Manager) StopEthTxSender() error { + return StopComponent("eth-tx-manager") +} - // Get network chain id - chainID, err := client.NetworkID(context.Background()) - if err != nil { - return err - } +// StartSequencer starts the sequencer +func (m *Manager) StartSequencer() error { + return StartComponent("seq") +} - auth, err := GetAuth(l1AccHexPrivateKey, chainID.Uint64()) - if err != nil { - return err - } +// StopSequencer stops the sequencer +func (m *Manager) StopSequencer() error { + return StopComponent("seq") +} - // Getting l1 info - gasPrice, err := client.SuggestGasPrice(context.Background()) - if err != nil { - return err - } +// StartSequenceSender starts the sequence sender +func (m *Manager) StartSequenceSender() error { + return StartComponent("seqsender") +} - // Send some Ether from l1Acc to sequencer acc - fromAddress := common.HexToAddress(l1AccHexAddress) - nonce, err := client.PendingNonceAt(context.Background(), fromAddress) - if err != nil { - return err - } +// StopSequenceSender stops the sequence sender +func (m *Manager) StopSequenceSender() error { + return StopComponent("seqsender") +} - const ( - gasLimit = 21000 - OneEther = 1000000000000000000 - ) - toAddress := common.HexToAddress(m.cfg.Sequencer.Address) - tx := types.NewTransaction(nonce, toAddress, big.NewInt(OneEther), uint64(gasLimit), gasPrice, nil) - signedTx, err := auth.Signer(auth.From, tx) +// Teardown stops all the components. +func Teardown() error { + err := stopNode() if err != nil { return err } - err = client.SendTransaction(context.Background(), signedTx) + err = stopNetwork() if err != nil { return err } - // Wait eth transfer to be mined - err = WaitTxToBeMined(client, signedTx.Hash(), DefaultTxMinedDeadline) - if err != nil { - return err - } + return nil +} - // Create matic maticTokenSC sc instance - maticTokenSC, err := NewToken(common.HexToAddress(maticTokenAddress), client) +// TeardownPermissionless stops all the components. +func TeardownPermissionless() error { + err := stopPermissionlessNode() if err != nil { return err } - // Send matic to sequencer - maticAmount, ok := big.NewInt(0).SetString("100000000000000000000000", encoding.Base10) - if !ok { - return fmt.Errorf("Error setting matic amount") - } - - tx, err = maticTokenSC.Transfer(auth, toAddress, maticAmount) + err = stopNetwork() if err != nil { return err } - // wait matic transfer to be mined - err = WaitTxToBeMined(client, tx.Hash(), DefaultTxMinedDeadline) - if err != nil { - return err - } + return nil +} - // Check matic balance - b, err := maticTokenSC.BalanceOf(&bind.CallOpts{}, toAddress) +func initState(maxCumulativeGasUsed uint64) (*state.State, error) { + sqlDB, err := db.NewSQLDB(stateDBCfg) if err != nil { - return err + return nil, err } - if b.Cmp(maticAmount) < 0 { - return fmt.Errorf("Minimum amount is: %v but found: %v", maticAmount.Text(encoding.Base10), b.Text(encoding.Base10)) - } + ctx := context.Background() + stateDb := state.NewPostgresStorage(sqlDB) + executorClient, _, _ := executor.NewExecutorClient(ctx, executorConfig) + stateDBClient, _, _ := merkletree.NewMTDBServiceClient(ctx, merkleTreeConfig) + stateTree := merkletree.NewStateTree(stateDBClient) - // Create sequencer auth - auth, err = GetAuth(m.cfg.Sequencer.PrivateKey, chainID.Uint64()) - if err != nil { - return err + stateCfg := state.Config{ + MaxCumulativeGasUsed: maxCumulativeGasUsed, } - // approve tokens to be used by PoE SC on behalf of the sequencer - tx, err = maticTokenSC.Approve(auth, common.HexToAddress(poeAddress), maticAmount) + eventStorage, err := nileventstorage.NewNilEventStorage() if err != nil { - return err + return nil, err } + eventLog := event.NewEventLog(event.Config{}, eventStorage) - err = WaitTxToBeMined(client, tx.Hash(), DefaultTxMinedDeadline) - if err != nil { - return err - } - return nil + st := state.NewState(stateCfg, stateDb, executorClient, stateTree, eventLog) + return st, nil } // StartNetwork starts the L1 network container @@ -453,7 +489,13 @@ func (m *Manager) StartNode() error { return StartComponent("node", nodeUpCondition) } -func approveMatic() error { +// StartTrustedAndPermissionlessNode starts the node container +func (m *Manager) StartTrustedAndPermissionlessNode() error { + return StartComponent("permissionless", nodeUpCondition) +} + +// ApproveMatic runs the approving matic command +func ApproveMatic() error { return StartComponent("approve-matic") } @@ -461,8 +503,28 @@ func stopNode() error { return StopComponent("node") } +func stopPermissionlessNode() error { + return StopComponent("permissionless") +} + func runCmd(c *exec.Cmd) error { - c.Dir = "../.." + dir, err := os.Getwd() + if err != nil { + log.Fatalf("failed to get current work directory: %v", err) + } + + if strings.Contains(dir, cmdFolder) { + // Making the change dir to work in any nesting directory level inside cmd folder + base := filepath.Base(dir) + for base != cmdFolder { + dir = filepath.Dir(dir) + base = filepath.Base(dir) + } + } else { + dir = fmt.Sprintf("../../%s", cmdFolder) + } + c.Dir = dir + c.Stdout = os.Stdout c.Stderr = os.Stderr return c.Run() @@ -503,8 +565,13 @@ func RunMakeTarget(target string) error { // GetDefaultOperationsConfig provides a default configuration to run the environment func GetDefaultOperationsConfig() *Config { return &Config{ - State: &state.Config{MaxCumulativeGasUsed: DefaultMaxCumulativeGasUsed}, - Sequencer: &SequencerConfig{Address: DefaultSequencerAddress, PrivateKey: DefaultSequencerPrivateKey}, + State: &state.Config{MaxCumulativeGasUsed: DefaultMaxCumulativeGasUsed}, + SequenceSender: &SequenceSenderConfig{ + WaitPeriodSendSequence: DefaultWaitPeriodSendSequence, + LastBatchVirtualizationTimeMaxWaitPeriod: DefaultWaitPeriodSendSequence, + MaxTxSizeForL1: DefaultMaxTxSizeForL1, + SenderAddress: DefaultSequencerAddress, + PrivateKey: DefaultSequencerPrivateKey}, } } @@ -533,7 +600,4 @@ func initOrResetDB() { if err := dbutils.InitOrResetPool(poolDBCfg); err != nil { panic(err) } - if err := dbutils.InitOrResetRPC(rpcDBCfg); err != nil { - panic(err) - } } diff --git a/test/operations/wait.go b/test/operations/wait.go index b951140359..45fa56d0c4 100644 --- a/test/operations/wait.go +++ b/test/operations/wait.go @@ -4,18 +4,22 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" - "io/ioutil" + "io" "math/big" "net/http" "os" "os/signal" "time" - "github.com/0xPolygonHermez/zkevm-node/jsonrpc" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/jsonrpc/client" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -26,7 +30,7 @@ const ( // DefaultInterval is a time interval DefaultInterval = 2 * time.Millisecond // DefaultDeadline is a time interval - DefaultDeadline = 30 * time.Second + DefaultDeadline = 2 * time.Minute // DefaultTxMinedDeadline is a time interval DefaultTxMinedDeadline = 5 * time.Second ) @@ -70,14 +74,66 @@ func Poll(interval, deadline time.Duration, condition ConditionFunc) error { type ethClienter interface { ethereum.TransactionReader ethereum.ContractCaller + bind.DeployBackend } // WaitTxToBeMined waits until a tx has been mined or the given timeout expires. -func WaitTxToBeMined(client ethClienter, hash common.Hash, timeout time.Duration) error { - ctx := context.Background() - return Poll(DefaultInterval, timeout, func() (bool, error) { - return txMinedCondition(ctx, client, hash) - }) +func WaitTxToBeMined(parentCtx context.Context, client ethClienter, tx *types.Transaction, timeout time.Duration) error { + ctx, cancel := context.WithTimeout(parentCtx, timeout) + defer cancel() + receipt, err := bind.WaitMined(ctx, client, tx) + if errors.Is(err, context.DeadlineExceeded) { + return err + } else if err != nil { + log.Errorf("error waiting tx %s to be mined: %w", tx.Hash(), err) + return err + } + if receipt.Status == types.ReceiptStatusFailed { + // Get revert reason + reason, reasonErr := RevertReason(ctx, client, tx, receipt.BlockNumber) + if reasonErr != nil { + reason = reasonErr.Error() + } + return fmt.Errorf("transaction has failed, reason: %s, receipt: %+v. tx: %+v, gas: %v", reason, receipt, tx, tx.Gas()) + } + log.Debug("Transaction successfully mined: ", tx.Hash()) + return nil +} + +// RevertReason returns the revert reason for a tx that has a receipt with failed status +func RevertReason(ctx context.Context, c ethClienter, tx *types.Transaction, blockNumber *big.Int) (string, error) { + if tx == nil { + return "", nil + } + + from, err := types.Sender(types.NewEIP155Signer(tx.ChainId()), tx) + if err != nil { + signer := types.LatestSignerForChainID(tx.ChainId()) + from, err = types.Sender(signer, tx) + if err != nil { + return "", err + } + } + msg := ethereum.CallMsg{ + From: from, + To: tx.To(), + Gas: tx.Gas(), + + Value: tx.Value(), + Data: tx.Data(), + } + hex, err := c.CallContract(ctx, msg, blockNumber) + if err != nil { + return "", err + } + + unpackedMsg, err := abi.UnpackRevert(hex) + if err != nil { + log.Warnf("failed to get the revert message for tx %v: %v", tx.Hash(), err) + return "", errors.New("execution reverted") + } + + return unpackedMsg, nil } // WaitGRPCHealthy waits for a gRPC endpoint to be responding according to the @@ -97,8 +153,32 @@ func WaitL2BlockToBeConsolidated(l2Block *big.Int, timeout time.Duration) error // WaitL2BlockToBeVirtualized waits until a L2 Block has been virtualized or the given timeout expires. func WaitL2BlockToBeVirtualized(l2Block *big.Int, timeout time.Duration) error { + l2NetworkURL := "http://localhost:8123" + return Poll(DefaultInterval, timeout, func() (bool, error) { + return l2BlockVirtualizationCondition(l2Block, l2NetworkURL) + }) +} + +// WaitL2BlockToBeVirtualizedCustomRPC waits until a L2 Block has been virtualized or the given timeout expires. +func WaitL2BlockToBeVirtualizedCustomRPC(l2Block *big.Int, timeout time.Duration, l2NetworkURL string) error { return Poll(DefaultInterval, timeout, func() (bool, error) { - return l2BlockVirtualizationCondition(l2Block) + return l2BlockVirtualizationCondition(l2Block, l2NetworkURL) + }) +} + +// WaitBatchToBeVirtualized waits until a Batch has been virtualized or the given timeout expires. +func WaitBatchToBeVirtualized(batchNum uint64, timeout time.Duration, state *state.State) error { + ctx := context.Background() + return Poll(DefaultInterval, timeout, func() (bool, error) { + return state.IsBatchVirtualized(ctx, batchNum, nil) + }) +} + +// WaitBatchToBeConsolidated waits until a Batch has been consolidated/verified or the given timeout expires. +func WaitBatchToBeConsolidated(batchNum uint64, timeout time.Duration, state *state.State) error { + ctx := context.Background() + return Poll(DefaultInterval, timeout, func() (bool, error) { + return state.IsBatchConsolidated(ctx, batchNum, nil) }) } @@ -127,7 +207,7 @@ func NodeUpCondition(target string) (bool, error) { }() } - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { return false, err @@ -135,7 +215,9 @@ func NodeUpCondition(target string) (bool, error) { r := struct { Result bool - }{} + }{ + Result: true, + } err = json.Unmarshal(body, &r) if err != nil { return false, err @@ -184,63 +266,10 @@ func grpcHealthyCondition(address string) (bool, error) { return done, nil } -// txMinedCondition -func txMinedCondition(ctx context.Context, client ethClienter, hash common.Hash) (bool, error) { - // Get tx status - tx, isPending, err := client.TransactionByHash(ctx, hash) - if err == ethereum.NotFound || isPending { - return false, nil - } - if err != nil { - return false, err - } - // Check if tx has failed - receipt, err := client.TransactionReceipt(ctx, hash) - if err != nil { - return false, err - } - if receipt.Status == types.ReceiptStatusFailed { - // Get revert reason - reason, reasonErr := revertReason(ctx, client, tx, receipt.BlockNumber) - if reasonErr != nil { - reason = reasonErr.Error() - } - return false, fmt.Errorf("transaction has failed, reason: %s, receipt: %+v. tx: %+v, gas: %v", reason, receipt, tx, tx.Gas()) - } - return true, nil -} - -func revertReason(ctx context.Context, c ethClienter, tx *types.Transaction, blockNumber *big.Int) (string, error) { - from, err := types.Sender(types.NewEIP155Signer(tx.ChainId()), tx) - if err != nil { - signer := types.LatestSignerForChainID(tx.ChainId()) - from, err = types.Sender(signer, tx) - if err != nil { - return "", err - } - } - msg := ethereum.CallMsg{ - From: from, - To: tx.To(), - Gas: tx.Gas(), - - Value: tx.Value(), - Data: tx.Data(), - } - hex, err := c.CallContract(ctx, msg, blockNumber) - if err != nil { - return "", err - } - - reasonOffset := new(big.Int).SetBytes(hex[4 : 4+32]) - reason := string(hex[4+32+int(reasonOffset.Uint64()):]) - return reason, nil -} - // l2BlockConsolidationCondition func l2BlockConsolidationCondition(l2Block *big.Int) (bool, error) { l2NetworkURL := "http://localhost:8123" - response, err := jsonrpc.JSONRPCCall(l2NetworkURL, "zkevm_isL2BlockConsolidated", l2Block.Uint64()) + response, err := client.JSONRPCCall(l2NetworkURL, "zkevm_isBlockConsolidated", hex.EncodeBig(l2Block)) if err != nil { return false, err } @@ -256,9 +285,8 @@ func l2BlockConsolidationCondition(l2Block *big.Int) (bool, error) { } // l2BlockVirtualizationCondition -func l2BlockVirtualizationCondition(l2Block *big.Int) (bool, error) { - l2NetworkURL := "http://localhost:8123" - response, err := jsonrpc.JSONRPCCall(l2NetworkURL, "zkevm_isL2BlockVirtualized", l2Block.Uint64()) +func l2BlockVirtualizationCondition(l2Block *big.Int, l2NetworkURL string) (bool, error) { + response, err := client.JSONRPCCall(l2NetworkURL, "zkevm_isBlockVirtualized", hex.EncodeBig(l2Block)) if err != nil { return false, err } diff --git a/test/scripts/batchsender/README.md b/test/scripts/batchsender/README.md new file mode 100644 index 0000000000..ffd729388d --- /dev/null +++ b/test/scripts/batchsender/README.md @@ -0,0 +1,71 @@ +# Batchsender + +## Overview + +This script allows to send a specified number of (empty) batch transactions to +L1. Optionally it can wait for the batch to be verified. The script interacts +with L1 only. Basically it acts like a sequencer but without building a real +rollup. It can be useful to test the Synchronizer and the Aggregator. + +## Usage + +The script can be installed running `go install` from this folder. + +### Examples + +- Send 1 batch: + +```sh +$ batchsender +``` + +- Send 42 batches: + +```sh +$ batchsender send 42 +``` + +## Flags + +### `--sequences, -s ` + +Send the specified number of sequences, each one filled with the provided +number of batches. + +### Examples + +- Send 2 sequences with 42 batches each: + +```sh +$ batchsender -s 2 send 42 +``` + +### `--wait, -w` + +Wait for batches to be verified on L1. + +### Examples + +- Send 1 batch and wait for its proof: + +```sh +$ batchsender -w send +``` + +- Send 2 sequences with 42 batches each and wait for the proofs: + +```sh +$ batchsender -w -s 2 send 42 +``` + +### `--verbose, -v` + +Prints verbose output to the console. + +### Examples + +- Send 42 batches with verbose logs and wait for the proofs: + +```sh +$ batchsender -v -w send 42 +``` diff --git a/test/scripts/batchsender/main.go b/test/scripts/batchsender/main.go new file mode 100644 index 0000000000..6cf3717052 --- /dev/null +++ b/test/scripts/batchsender/main.go @@ -0,0 +1,338 @@ +package main + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "os" + "strconv" + "time" + + "github.com/0xPolygonHermez/zkevm-node/config" + "github.com/0xPolygonHermez/zkevm-node/etherman" + ethmanTypes "github.com/0xPolygonHermez/zkevm-node/etherman/types" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/mitchellh/mapstructure" + "github.com/spf13/viper" + "github.com/urfave/cli/v2" +) + +const ( + flagSequencesName = "sequences" + flagWaitName = "wait" + flagVerboseName = "verbose" +) + +var ( + flagSequences = cli.Uint64Flag{ + Name: flagSequencesName, + Aliases: []string{"s"}, + Usage: "send batches for the provided number of sequences.", + Required: false, + } + flagWait = cli.BoolFlag{ + Name: flagWaitName, + Aliases: []string{"w"}, + Usage: "wait batch transaction to be confirmed", + Required: false, + } + flagVerbose = cli.BoolFlag{ + Name: flagVerboseName, + Aliases: []string{"v"}, + Usage: "output verbose logs", + Required: false, + } +) + +func main() { + batchsender := cli.NewApp() + batchsender.Name = "batchsender" + batchsender.Usage = "send batch transactions to L1" + batchsender.Description = `This tool allows to send a specified number of batch transactions to L1. +Optionally it can wait for the batches to be validated.` + batchsender.DefaultCommand = "send" + batchsender.Flags = []cli.Flag{&flagSequences, &flagWait, &flagVerbose} + batchsender.Commands = []*cli.Command{ + { + Before: setLogLevel, + Name: "send", + Aliases: []string{}, + Usage: "Sends the specified number of batch transactions to L1", + Description: `This command sends the specified number of batches to L1. +If --sequences flag is used, the number of batches is repeated for the number of sequences provided. +If --wait flag is used, it waits for the corresponding validation transaction.`, + ArgsUsage: "number of batches to be sent (default: 1)", + Action: sendBatches, + }, + } + + err := batchsender.Run(os.Args) + if err != nil { + log.Fatal(err) + os.Exit(1) + } +} + +func setLogLevel(ctx *cli.Context) error { + logLevel := "info" + if ctx.Bool(flagVerboseName) { + logLevel = "debug" + } + + log.Init(log.Config{ + Level: logLevel, + Outputs: []string{"stderr"}, + }) + return nil +} + +func sendBatches(cliCtx *cli.Context) error { + ctx := cliCtx.Context + + // retrieve default configuration + var cfg config.Config + viper.SetConfigType("toml") + err := viper.ReadConfig(bytes.NewBuffer([]byte(config.DefaultValues))) + if err != nil { + return err + } + err = viper.Unmarshal(&cfg, viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())) + if err != nil { + return err + } + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + if err != nil { + return err + } + + ethMan, err := etherman.NewClient(cfg.Etherman, cfg.NetworkConfig.L1Config) + if err != nil { + return err + } + + err = ethMan.AddOrReplaceAuth(*auth) + if err != nil { + return err + } + log.Info("Using address: ", auth.From) + + wait := cliCtx.Bool(flagWaitName) + + nBatches := 1 // send 1 batch by default + if cliCtx.NArg() > 0 { + nBatchesArgStr := cliCtx.Args().Get(0) + nBatchesArg, err := strconv.Atoi(nBatchesArgStr) + if err == nil { + nBatches = nBatchesArg + } + } + + nSequences := int(cliCtx.Uint64(flagSequencesName)) + + var sentTxs []*ethTypes.Transaction + sentTxsMap := make(map[common.Hash]struct{}) + + var duration time.Duration + if nBatches > 1 { + duration = 500 + } + + // here the behavior is different: + // - if the `--sequences` flag is used we send ns sequences filled with nb batches each + // - if the flag is not used we send one sequence for each batch + var ns, nb int + if nSequences == 0 { + ns = nBatches + nb = 1 + } else { + ns = nSequences + nb = nBatches + } + + nonce, err := ethMan.CurrentNonce(ctx, auth.From) + if err != nil { + err := fmt.Errorf("failed to get current nonce: %w", err) + log.Error(err.Error()) + return err + } + + for i := 0; i < ns; i++ { + currentBlock, err := ethMan.EthClient.BlockByNumber(ctx, nil) + if err != nil { + return err + } + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + seqs := make([]ethmanTypes.Sequence, 0, nBatches) + for i := 0; i < nb; i++ { + // empty rollup + seqs = append(seqs, ethmanTypes.Sequence{ + GlobalExitRoot: common.HexToHash("0x"), + BatchL2Data: []byte{}, + Timestamp: int64(currentBlock.Time() - 1), // fit in latest-sequence < > current-block rage + }) + } + + // send to L1 + to, data, err := ethMan.BuildSequenceBatchesTxData(auth.From, seqs) + if err != nil { + return err + } + tx := ethTypes.NewTx(ðTypes.LegacyTx{ + To: to, + Data: data, + }) + signedTx, err := ethMan.SignTx(ctx, auth.From, tx) + if err != nil { + return err + } + err = ethMan.SendTx(ctx, signedTx) + if err != nil { + return err + } + gas, err := ethMan.EstimateGas(ctx, auth.From, to, nil, data) + if err != nil { + err := fmt.Errorf("failed to estimate gas: %w", err) + log.Error(err.Error()) + return err + } + // get gas price + gasPrice, err := ethMan.SuggestedGasPrice(ctx) + if err != nil { + err := fmt.Errorf("failed to get suggested gas price: %w", err) + log.Error(err.Error()) + return err + } + tx = ethTypes.NewTx(ðTypes.LegacyTx{ + Nonce: nonce, + Gas: gas + uint64(i), + GasPrice: gasPrice, + To: to, + Data: data, + }) + signedTx, err = ethMan.SignTx(ctx, auth.From, tx) + if err != nil { + log.Error(err.Error()) + return err + } + err = ethMan.SendTx(ctx, signedTx) + if err != nil { + log.Error(err.Error()) + return err + } + + log.Info("TxHash: ", signedTx.Hash()) + sentTxs = append(sentTxs, signedTx) + sentTxsMap[signedTx.Hash()] = struct{}{} + + time.Sleep(duration * time.Millisecond) + } + + sentBatches := len(sentTxs) + + if wait { // wait proofs + log.Info("Waiting for transactions to be confirmed...") + time.Sleep(time.Second) + + virtualBatches := make(map[uint64]common.Hash) + verifiedBatches := make(map[uint64]struct{}) + loggedBatches := make(map[uint64]struct{}) + + miningTimeout := 180 * time.Second //nolint:gomnd + waitTimeout := time.Duration(180*len(sentTxs)) * time.Second //nolint:gomnd + done := make(chan struct{}) + + for _, tx := range sentTxs { + err := operations.WaitTxToBeMined(ctx, ethMan.EthClient, tx, miningTimeout) + if err != nil { + return err + } + } + + for { + select { + case <-time.After(waitTimeout): + return errors.New("deadline exceeded") + case <-done: + success(sentBatches) + return nil + default: + txLoop: + for _, tx := range sentTxs { + // get rollup tx block number + receipt, err := ethMan.EthClient.TransactionReceipt(ctx, tx.Hash()) + if err != nil { + return err + } + + fromBlock := receipt.BlockNumber + toBlock := new(big.Int).Add(fromBlock, new(big.Int).SetUint64(cfg.Synchronizer.SyncChunkSize)) + query := ethereum.FilterQuery{ + FromBlock: fromBlock, + ToBlock: toBlock, + Addresses: ethMan.SCAddresses, + } + logs, err := ethMan.EthClient.FilterLogs(ctx, query) + if err != nil { + return err + } + for _, vLog := range logs { + switch vLog.Topics[0] { + case etherman.SequencedBatchesSigHash(): + if vLog.TxHash == tx.Hash() { // ignore other txs happening on L1 + sb, err := ethMan.ZkEVM.ParseSequenceBatches(vLog) + if err != nil { + return err + } + + virtualBatches[sb.NumBatch] = vLog.TxHash + + if _, logged := loggedBatches[sb.NumBatch]; !logged { + log.Infof("Batch [%d] virtualized in TxHash [%v]", sb.NumBatch, vLog.TxHash) + loggedBatches[sb.NumBatch] = struct{}{} + } + } + case etherman.TrustedVerifyBatchesSigHash(): + vb, err := ethMan.ZkEVM.ParseVerifyBatchesTrustedAggregator(vLog) + if err != nil { + return err + } + + if _, verified := verifiedBatches[vb.NumBatch]; !verified { + log.Infof("Batch [%d] verified in TxHash [%v]", vb.NumBatch, vLog.TxHash) + verifiedBatches[vb.NumBatch] = struct{}{} + } + + // batch is verified, remove it from the txs set + delete(sentTxsMap, virtualBatches[vb.NumBatch]) + if len(sentTxsMap) == 0 { + close(done) + break txLoop + } + } + } + + // wait for verifications + time.Sleep(time.Second) //nolint:gomnd + } + } + } + } + + success(sentBatches) + return nil +} + +func success(nBatches int) { + if nBatches > 1 { + log.Infof("Successfully sent %d batches", nBatches) + } else { + log.Info("Successfully sent 1 batch") + } +} diff --git a/scripts/cmd/compilesc.go b/test/scripts/cmd/compilesc.go similarity index 75% rename from scripts/cmd/compilesc.go rename to test/scripts/cmd/compilesc.go index 4f98c715bc..61afffe54b 100644 --- a/scripts/cmd/compilesc.go +++ b/test/scripts/cmd/compilesc.go @@ -1,7 +1,7 @@ package main import ( - "github.com/0xPolygonHermez/zkevm-node/scripts/cmd/compilesc" + "github.com/0xPolygonHermez/zkevm-node/test/scripts/cmd/compilesc" "github.com/urfave/cli/v2" ) diff --git a/scripts/cmd/compilesc/manager.go b/test/scripts/cmd/compilesc/manager.go similarity index 98% rename from scripts/cmd/compilesc/manager.go rename to test/scripts/cmd/compilesc/manager.go index 1ced8c549e..f5a276b787 100644 --- a/scripts/cmd/compilesc/manager.go +++ b/test/scripts/cmd/compilesc/manager.go @@ -3,7 +3,6 @@ package compilesc import ( "fmt" "io/fs" - "io/ioutil" "os" "os/exec" "os/user" @@ -70,7 +69,7 @@ func NewManager(basePath string) (*Manager, error) { // Run executes the compilation of smart contracts and generation of golang // bindings. func (cm *Manager) Run() error { - yamlFile, err := ioutil.ReadFile(path.Join(cm.absoluteBasePath, "index.yaml")) + yamlFile, err := os.ReadFile(path.Join(cm.absoluteBasePath, "index.yaml")) if err != nil { return err } diff --git a/scripts/cmd/dependencies.go b/test/scripts/cmd/dependencies.go similarity index 90% rename from scripts/cmd/dependencies.go rename to test/scripts/cmd/dependencies.go index 36d343fe6a..9ea7471008 100644 --- a/scripts/cmd/dependencies.go +++ b/test/scripts/cmd/dependencies.go @@ -1,7 +1,7 @@ package main import ( - "github.com/0xPolygonHermez/zkevm-node/scripts/cmd/dependencies" + "github.com/0xPolygonHermez/zkevm-node/test/scripts/cmd/dependencies" "github.com/urfave/cli/v2" ) diff --git a/scripts/cmd/dependencies/files.go b/test/scripts/cmd/dependencies/files.go similarity index 100% rename from scripts/cmd/dependencies/files.go rename to test/scripts/cmd/dependencies/files.go diff --git a/scripts/cmd/dependencies/files_test.go b/test/scripts/cmd/dependencies/files_test.go similarity index 100% rename from scripts/cmd/dependencies/files_test.go rename to test/scripts/cmd/dependencies/files_test.go diff --git a/scripts/cmd/dependencies/github.go b/test/scripts/cmd/dependencies/github.go similarity index 96% rename from scripts/cmd/dependencies/github.go rename to test/scripts/cmd/dependencies/github.go index 548cf22bdb..0dc98ef0b5 100644 --- a/scripts/cmd/dependencies/github.go +++ b/test/scripts/cmd/dependencies/github.go @@ -1,7 +1,6 @@ package dependencies import ( - "net" "os" "path/filepath" @@ -14,7 +13,6 @@ import ( "github.com/go-git/go-git/v5/plumbing/transport/ssh" "github.com/go-git/go-git/v5/storage/memory" "github.com/spf13/afero" - gossh "golang.org/x/crypto/ssh" ) type githubManager struct { @@ -88,11 +86,7 @@ func (gm *githubManager) determineAuth() (transport.AuthMethod, error) { if err != nil { return nil, err } - auth.HostKeyCallbackHelper = ssh.HostKeyCallbackHelper{ - HostKeyCallback: func(hostname string, remote net.Addr, key gossh.PublicKey) error { - return nil - }, - } + return auth, nil } diff --git a/scripts/cmd/dependencies/github_test.go b/test/scripts/cmd/dependencies/github_test.go similarity index 100% rename from scripts/cmd/dependencies/github_test.go rename to test/scripts/cmd/dependencies/github_test.go diff --git a/scripts/cmd/dependencies/images.go b/test/scripts/cmd/dependencies/images.go similarity index 100% rename from scripts/cmd/dependencies/images.go rename to test/scripts/cmd/dependencies/images.go diff --git a/scripts/cmd/dependencies/images_test.go b/test/scripts/cmd/dependencies/images_test.go similarity index 100% rename from scripts/cmd/dependencies/images_test.go rename to test/scripts/cmd/dependencies/images_test.go diff --git a/scripts/cmd/dependencies/manager.go b/test/scripts/cmd/dependencies/manager.go similarity index 100% rename from scripts/cmd/dependencies/manager.go rename to test/scripts/cmd/dependencies/manager.go diff --git a/scripts/cmd/dependencies/protobuffers.go b/test/scripts/cmd/dependencies/protobuffers.go similarity index 100% rename from scripts/cmd/dependencies/protobuffers.go rename to test/scripts/cmd/dependencies/protobuffers.go diff --git a/scripts/cmd/dependencies/testvectors.go b/test/scripts/cmd/dependencies/testvectors.go similarity index 100% rename from scripts/cmd/dependencies/testvectors.go rename to test/scripts/cmd/dependencies/testvectors.go diff --git a/scripts/cmd/main.go b/test/scripts/cmd/main.go similarity index 100% rename from scripts/cmd/main.go rename to test/scripts/cmd/main.go diff --git a/scripts/deploy_sc/main.go b/test/scripts/deploy_sc/main.go similarity index 87% rename from scripts/deploy_sc/main.go rename to test/scripts/deploy_sc/main.go index 98760b7045..7cf5c404a9 100644 --- a/scripts/deploy_sc/main.go +++ b/test/scripts/deploy_sc/main.go @@ -57,12 +57,12 @@ func main() { log.Debugf("Sending TX to deploy Counter SC") _, tx, counterSC, err := Counter.DeployCounter(auth, client) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) log.Debugf("Calling Increment method from Counter SC") tx, err = counterSC.Increment(auth) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) fmt.Println() @@ -70,12 +70,12 @@ func main() { log.Debugf("Sending TX to deploy EmitLog SC") _, tx, emitLogSC, err := EmitLog.DeployEmitLog(auth, client) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) log.Debugf("Calling EmitLogs method from EmitLog SC") tx, err = emitLogSC.EmitLogs(auth) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) fmt.Println() @@ -84,12 +84,12 @@ func main() { log.Debugf("Sending TX to deploy ERC20 SC") _, tx, erc20SC, err := ERC20.DeployERC20(auth, client, "Test Coin", "TCO") chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) log.Debugf("Sending TX to do a ERC20 mint") tx, err = erc20SC.Mint(auth, mintAmount) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) transferAmount, _ := big.NewInt(0).SetString("900000000000000000000", encoding.Base10) log.Debugf("Sending TX to do a ERC20 transfer") @@ -100,9 +100,9 @@ func main() { invalidTx, err := erc20SC.Transfer(auth, common.HexToAddress(receiverAddr), transferAmount) chkErr(err) log.Debugf("Invalid ERC20 tx hash: %v", invalidTx.Hash()) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) - operations.WaitTxToBeMined(client, invalidTx.Hash(), txTimeout) //nolint:errcheck + operations.WaitTxToBeMined(ctx, client, invalidTx, txTimeout) //nolint:errcheck chkErr(err) auth.Nonce = nil fmt.Println() @@ -112,12 +112,12 @@ func main() { log.Debugf("Sending TX to deploy Storage SC") _, tx, storageSC, err := Storage.DeployStorage(auth, client) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) log.Debugf("Calling Store method from Storage SC") tx, err = storageSC.Store(auth, big.NewInt(numberToStore)) chkErr(err) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) fmt.Println() @@ -138,7 +138,7 @@ func main() { log.Debugf("Sending Invalid TX to transfer ETH") nonce := tx.Nonce() + 1 ethTransfer(ctx, client, auth, to, transferAmount, &nonce) - err = operations.WaitTxToBeMined(client, tx.Hash(), txTimeout) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) chkErr(err) fmt.Println() } diff --git a/scripts/init_network/main.go b/test/scripts/init_network/main.go similarity index 94% rename from scripts/init_network/main.go rename to test/scripts/init_network/main.go index 1202e3412a..97de6e4d2e 100644 --- a/scripts/init_network/main.go +++ b/test/scripts/init_network/main.go @@ -22,7 +22,7 @@ package main // L1ETHAmountToSequencer: "200000000000000000000", // L1MaticAmountToSequencer: "200000000000000000000000", // }, -// SequencerAddress: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", +// sequencerAddress: "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", // SequencerPrivateKey: "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", // TxTimeout: time.Minute, // }); err != nil { diff --git a/scripts/postgres/prover-user.sql b/test/scripts/postgres/prover-user.sql similarity index 100% rename from scripts/postgres/prover-user.sql rename to test/scripts/postgres/prover-user.sql diff --git a/scripts/postgres/run.sh b/test/scripts/postgres/run.sh old mode 100755 new mode 100644 similarity index 100% rename from scripts/postgres/run.sh rename to test/scripts/postgres/run.sh diff --git a/test/scripts/sendForcedBatch/README.md b/test/scripts/sendForcedBatch/README.md new file mode 100644 index 0000000000..c12d1eaca4 --- /dev/null +++ b/test/scripts/sendForcedBatch/README.md @@ -0,0 +1,5 @@ + +Command: +``` +go run main.go send --url http://localhost:8545 --smc 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 +``` \ No newline at end of file diff --git a/test/scripts/sendForcedBatch/main.go b/test/scripts/sendForcedBatch/main.go new file mode 100644 index 0000000000..1cb2f1ac35 --- /dev/null +++ b/test/scripts/sendForcedBatch/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "os" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/urfave/cli/v2" +) + +const ( + flagL1URLName = "url" + flagSmcAddrName = "smc" + miningTimeout = 180 +) + +var ( + flagL1URL = cli.StringFlag{ + Name: flagL1URLName, + Aliases: []string{"u"}, + Usage: "L1 node url", + Required: true, + } + flagSmcAddr = cli.StringFlag{ + Name: flagSmcAddrName, + Aliases: []string{"a"}, + Usage: "Smart contract address", + Required: true, + } +) + +func main() { + fbatchsender := cli.NewApp() + fbatchsender.Name = "forcedBatchsender" + fbatchsender.Usage = "send forced batch transactions to L1" + fbatchsender.DefaultCommand = "send" + flags := []cli.Flag{&flagL1URL, &flagSmcAddr} + fbatchsender.Commands = []*cli.Command{ + { + Before: setLogLevel, + Name: "send", + Aliases: []string{}, + Flags: flags, + Action: sendForcedBatches, + }, + } + + err := fbatchsender.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} + +func setLogLevel(ctx *cli.Context) error { + logLevel := "debug" + log.Init(log.Config{ + Level: logLevel, + Outputs: []string{"stderr"}, + }) + return nil +} + +func sendForcedBatches(cliCtx *cli.Context) error { + ctx := cliCtx.Context + + url := cliCtx.String(flagL1URLName) + // Connect to ethereum node + ethClient, err := ethclient.Dial(url) + if err != nil { + log.Errorf("error connecting to %s: %+v", url, err) + return err + } + // Create smc client + poeAddr := common.HexToAddress(cliCtx.String(flagSmcAddrName)) + poe, err := polygonzkevm.NewPolygonzkevm(poeAddr, ethClient) + if err != nil { + return err + } + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + if err != nil { + return err + } + + log.Info("Using address: ", auth.From) + + num, err := poe.LastForceBatch(&bind.CallOpts{Pending: false}) + if err != nil { + log.Error("error getting lastForBatch number. Error : ", err) + return err + } + log.Info("Number of forceBatches in the smc: ", num) + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + if err != nil { + log.Error("error getting blockByNumber. Error: ", err) + return err + } + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + // Get tip + tip, err := poe.GetForcedBatchFee(&bind.CallOpts{Pending: false}) + if err != nil { + log.Error("error getting tip. Error: ", err) + return err + } + + // Allow forced batches in smart contract if disallowed + disallowed, err := poe.IsForcedBatchDisallowed(&bind.CallOpts{Pending: false}) + if err != nil { + log.Error("error getting isForcedBatchDisallowed. Error: ", err) + return err + } + if disallowed { + tx, err := poe.ActivateForceBatches(auth) + if err != nil { + log.Error("error sending activateForceBatches. Error: ", err) + return err + } + err = operations.WaitTxToBeMined(ctx, ethClient, tx, operations.DefaultTimeoutTxToBeMined) + if err != nil { + + log.Error("error waiting tx to be mined. Error: ", err) + return err + } + } + + // Send forceBatch + tx, err := poe.ForceBatch(auth, []byte{}, tip) + if err != nil { + log.Error("error sending forceBatch. Error: ", err) + return err + } + + log.Info("TxHash: ", tx.Hash()) + + time.Sleep(1 * time.Second) + + err = operations.WaitTxToBeMined(ctx, ethClient, tx, miningTimeout*time.Second) + if err != nil { + return err + } + + query := ethereum.FilterQuery{ + FromBlock: currentBlock.Number(), + Addresses: []common.Address{poeAddr}, + } + logs, err := ethClient.FilterLogs(ctx, query) + if err != nil { + return err + } + for _, vLog := range logs { + fb, err := poe.ParseForceBatch(vLog) + if err == nil { + log.Debugf("log decoded: %+v", fb) + ger := fb.LastGlobalExitRoot + log.Info("GlobalExitRoot: ", ger) + log.Info("Transactions: ", common.Bytes2Hex(fb.Transactions)) + fullBlock, err := ethClient.BlockByHash(ctx, vLog.BlockHash) + if err != nil { + log.Errorf("error getting hashParent. BlockNumber: %d. Error: %v", vLog.BlockNumber, err) + return err + } + log.Info("MinForcedTimestamp: ", fullBlock.Time()) + } + } + + return nil +} diff --git a/test/scripts/send_transfers/main.go b/test/scripts/send_transfers/main.go new file mode 100644 index 0000000000..136252b275 --- /dev/null +++ b/test/scripts/send_transfers/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "context" + "fmt" + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +func main() { + var networks = []struct { + Name string + URL string + ChainID uint64 + PrivateKey string + }{ + //{Name: "Local L1", URL: operations.DefaultL1NetworkURL, ChainID: operations.DefaultL1ChainID, PrivateKey: operations.DefaultSequencerPrivateKey}, + {Name: "Local L2", URL: operations.DefaultL2NetworkURL, ChainID: operations.DefaultL2ChainID, PrivateKey: operations.DefaultSequencerPrivateKey}, + } + + for _, network := range networks { + ctx := context.Background() + + log.Infof("connecting to %v: %v", network.Name, network.URL) + client, err := ethclient.Dial(network.URL) + chkErr(err) + log.Infof("connected") + + auth := operations.MustGetAuth(network.PrivateKey, network.ChainID) + chkErr(err) + + const receiverAddr = "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D" + + balance, err := client.BalanceAt(ctx, auth.From, nil) + chkErr(err) + log.Debugf("ETH Balance for %v: %v", auth.From, balance) + + // Valid ETH Transfer + balance, err = client.BalanceAt(ctx, auth.From, nil) + log.Debugf("ETH Balance for %v: %v", auth.From, balance) + chkErr(err) + transferAmount := big.NewInt(1) + log.Debugf("Transfer Amount: %v", transferAmount) + + nonce, err := client.NonceAt(ctx, auth.From, nil) + chkErr(err) + // var lastTxHash common.Hash + for i := 0; i < 1000; i++ { + nonce := nonce + uint64(i) + log.Debugf("Sending TX to transfer ETH") + to := common.HexToAddress(receiverAddr) + tx := ethTransfer(ctx, client, auth, to, transferAmount, &nonce) + fmt.Println("tx sent: ", tx.Hash().String()) + // lastTxHash = tx.Hash() + } + + // err = operations.WaitTxToBeMined(client, lastTxHash, txTimeout) + // chkErr(err) + } +} + +func ethTransfer(ctx context.Context, client *ethclient.Client, auth *bind.TransactOpts, to common.Address, amount *big.Int, nonce *uint64) *types.Transaction { + if nonce == nil { + log.Infof("reading nonce for account: %v", auth.From.Hex()) + var err error + n, err := client.NonceAt(ctx, auth.From, nil) + log.Infof("nonce: %v", n) + chkErr(err) + nonce = &n + } + + gasPrice, err := client.SuggestGasPrice(context.Background()) + chkErr(err) + + gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{To: &to}) + chkErr(err) + + tx := types.NewTransaction(*nonce, to, amount, gasLimit, gasPrice, nil) + + signedTx, err := auth.Signer(auth.From, tx) + chkErr(err) + + log.Infof("sending transfer tx") + err = client.SendTransaction(ctx, signedTx) + chkErr(err) + log.Infof("tx sent: %v", signedTx.Hash().Hex()) + + rlp, err := signedTx.MarshalBinary() + chkErr(err) + + log.Infof("tx rlp: %v", hex.EncodeToHex(rlp)) + + return signedTx +} + +func chkErr(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/test/scripts/sequenceForcedBatch/README.md b/test/scripts/sequenceForcedBatch/README.md new file mode 100644 index 0000000000..816317a7b2 --- /dev/null +++ b/test/scripts/sequenceForcedBatch/README.md @@ -0,0 +1,5 @@ + +Command: +``` +go run ./scripts/sequenceForcedBatch/main.go send --url http://localhost:8545 --smc 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 --ger 0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5 -tx 0x -t 1674730229 +``` \ No newline at end of file diff --git a/test/scripts/sequenceForcedBatch/main.go b/test/scripts/sequenceForcedBatch/main.go new file mode 100644 index 0000000000..ad4af0c6e6 --- /dev/null +++ b/test/scripts/sequenceForcedBatch/main.go @@ -0,0 +1,151 @@ +package main + +import ( + "os" + "time" + + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" + "github.com/0xPolygonHermez/zkevm-node/hex" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/urfave/cli/v2" +) + +const ( + flagL1URLName = "url" + flagSmcAddrName = "smc" + flagGerName = "ger" + flagTimestampName = "timestamp" + flagTransactionsName = "transactions" + miningTimeout = 180 +) + +var ( + flagL1URL = cli.StringFlag{ + Name: flagL1URLName, + Aliases: []string{"u"}, + Usage: "L1 node url", + Required: true, + } + flagSmcAddr = cli.StringFlag{ + Name: flagSmcAddrName, + Aliases: []string{"a"}, + Usage: "Smart contract address", + Required: true, + } + flagGer = cli.StringFlag{ + Name: flagGerName, + Aliases: []string{"g"}, + Usage: "Global exit root", + Required: true, + } + flagTimestamp = cli.StringFlag{ + Name: flagTimestampName, + Aliases: []string{"t"}, + Usage: "MinForcedTimestamp", + Required: true, + } + flagTransactions = cli.StringFlag{ + Name: flagTransactionsName, + Aliases: []string{"tx"}, + Usage: "Transactions", + Required: true, + } +) + +func main() { + fbatchsender := cli.NewApp() + fbatchsender.Name = "sequenceForcedBatchsender" + fbatchsender.Usage = "send sequencer forced batch transactions to L1" + fbatchsender.DefaultCommand = "send" + flags := []cli.Flag{&flagL1URL, &flagSmcAddr, &flagGer, &flagTimestamp, &flagTransactions} + fbatchsender.Commands = []*cli.Command{ + { + Before: setLogLevel, + Name: "send", + Aliases: []string{}, + Flags: flags, + Action: sendForcedBatches, + }, + } + + err := fbatchsender.Run(os.Args) + if err != nil { + log.Fatal(err) + } +} + +func setLogLevel(ctx *cli.Context) error { + logLevel := "debug" + log.Init(log.Config{ + Level: logLevel, + Outputs: []string{"stderr"}, + }) + return nil +} + +func sendForcedBatches(cliCtx *cli.Context) error { + ctx := cliCtx.Context + + url := cliCtx.String(flagL1URLName) + // Connect to ethereum node + ethClient, err := ethclient.Dial(url) + if err != nil { + log.Errorf("error connecting to %s: %+v", url, err) + return err + } + // Create smc client + poeAddr := common.HexToAddress(cliCtx.String(flagSmcAddrName)) + poe, err := polygonzkevm.NewPolygonzkevm(poeAddr, ethClient) + if err != nil { + return err + } + + auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL1ChainID) + if err != nil { + return err + } + + log.Info("Using address: ", auth.From) + + num, err := poe.LastForceBatch(&bind.CallOpts{Pending: false}) + if err != nil { + log.Error("error getting lastForBatch number. Error : ", err) + return err + } + log.Info("Number of forceBatches in the smc: ", num) + + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + if err != nil { + log.Error("error getting blockByNumber. Error: ", err) + return err + } + log.Debug("currentBlock.Time(): ", currentBlock.Time()) + + transactions, err := hex.DecodeHex(cliCtx.String(flagTransactionsName)) + if err != nil { + log.Error("error decoding txs. Error: ", err) + return err + } + fbData := []polygonzkevm.PolygonZkEVMForcedBatchData{{ + Transactions: transactions, + GlobalExitRoot: common.HexToHash(cliCtx.String(flagGerName)), + MinForcedTimestamp: cliCtx.Uint64(flagTimestampName), + }} + log.Warnf("%v, %+v", cliCtx.String(flagTransactionsName), fbData) + // Send forceBatch + tx, err := poe.SequenceForceBatches(auth, fbData) + if err != nil { + log.Error("error sending forceBatch. Error: ", err) + return err + } + + log.Info("TxHash: ", tx.Hash()) + + time.Sleep(1 * time.Second) + + return operations.WaitTxToBeMined(ctx, ethClient, tx, miningTimeout*time.Second) +} diff --git a/test/scripts/txsender/README.md b/test/scripts/txsender/README.md new file mode 100644 index 0000000000..082d0419d2 --- /dev/null +++ b/test/scripts/txsender/README.md @@ -0,0 +1,36 @@ +# Txsender + +## Overview + +This script allows to send a specified number of transactions to either L1 or +L2 (or both). Optionally it can wait for the transactions to be verified. + +## Usage + +The script can be installed running `go install` from this folder. + +## Examples + +- Send 1 transaction on L2: + +```sh +$ txsender +``` + +- Send 1 transaction on L2 and wait for it to be validated: + +```sh +$ txsender -w send +``` + +- Send 42 transactions on L1: + +```sh +$ txsender -n l1 send 42 +``` + +- Send 42 transactions both on L1 and L2 with verbose logs and wait for the validations: + +```sh +$ txsender -v -w -n l1 -n l2 send 42 +``` diff --git a/test/scripts/txsender/main.go b/test/scripts/txsender/main.go new file mode 100644 index 0000000000..fabb61ce26 --- /dev/null +++ b/test/scripts/txsender/main.go @@ -0,0 +1,217 @@ +package main + +import ( + "fmt" + "math/big" + "os" + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/urfave/cli/v2" +) + +const ( + flagNetworkName = "network" + flagWaitName = "wait" + flagVerboseName = "verbose" + flagNetworkLocalL1Key = "l1" + flagNetworkLocalL2Key = "l2" + defaultNetwork = flagNetworkLocalL2Key + + receiverAddr = "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D" +) + +type networkLayer int + +const ( + networkLayer1 networkLayer = iota + networkLayer2 +) + +var networks = map[string]struct { + Name string + URL string + ChainID uint64 + PrivateKey string + networkLayer +}{ + flagNetworkLocalL1Key: {Name: "Local L1", URL: operations.DefaultL1NetworkURL, ChainID: operations.DefaultL1ChainID, PrivateKey: operations.DefaultSequencerPrivateKey, networkLayer: networkLayer1}, + flagNetworkLocalL2Key: {Name: "Local L2", URL: operations.DefaultL2NetworkURL, ChainID: operations.DefaultL2ChainID, PrivateKey: operations.DefaultSequencerPrivateKey, networkLayer: networkLayer2}, +} + +var ( + flagNetwork = cli.StringSliceFlag{ + Name: flagNetworkName, + Aliases: []string{"n"}, + Usage: "list of networks on which to send transactions", + Required: false, + } + flagWait = cli.BoolFlag{ + Name: flagWaitName, + Aliases: []string{"w"}, + Usage: "wait transactions to be confirmed", + Required: false, + } + flagVerbose = cli.BoolFlag{ + Name: flagVerboseName, + Aliases: []string{"v"}, + Usage: "output verbose logs", + Required: false, + } +) + +func main() { + txsender := cli.NewApp() + txsender.Name = "txsender" + txsender.Flags = []cli.Flag{&flagNetwork, &flagWait, &flagVerbose} + txsender.Usage = "send transactions" + txsender.Description = `This tool allows to send a specified number of transactions. +Optionally it can wait for the transactions to be validated.` + txsender.DefaultCommand = "send" + txsender.Commands = []*cli.Command{ + { + Name: "send", + Before: setLogLevel, + Aliases: []string{}, + Usage: "Sends the specified number of transactions", + Description: `This command sends the specified number of transactions. +If --wait flag is used, it waits for the corresponding validation transaction.`, + ArgsUsage: "number of transactions to be sent (default: 1)", + Action: sendTxs, + }, + } + + err := txsender.Run(os.Args) + if err != nil { + log.Fatal(err) + os.Exit(1) + } +} + +func setLogLevel(ctx *cli.Context) error { + logLevel := "info" + if ctx.Bool(flagVerboseName) { + logLevel = "debug" + } + + log.Init(log.Config{ + Level: logLevel, + Outputs: []string{"stderr"}, + }) + return nil +} + +func sendTxs(cliCtx *cli.Context) error { + ctx := cliCtx.Context + + nTxs := 1 // send 1 tx by default + if cliCtx.NArg() > 0 { + nTxsArgStr := cliCtx.Args().Get(0) + nTxsArg, err := strconv.Atoi(nTxsArgStr) + if err == nil { + nTxs = nTxsArg + } + } + + selNetworks := cliCtx.StringSlice(flagNetworkName) + + // if no network selected, pick the default one + if selNetworks == nil { + selNetworks = []string{defaultNetwork} + } + + for _, selNetwork := range selNetworks { + network, ok := networks[selNetwork] + if !ok { + netKeys := make([]string, 0, len(networks)) + for net := range networks { + netKeys = append(netKeys, net) + } + return fmt.Errorf("please specify one or more of these networks: %v", netKeys) + } + log.Infof("connecting to %v: %v", network.Name, network.URL) + client, err := ethclient.Dial(network.URL) + if err != nil { + return err + } + log.Infof("connected") + + auth, err := operations.GetAuth(network.PrivateKey, network.ChainID) + if err != nil { + return err + } + + log.Infof("Sender Addr: %v", auth.From.String()) + + senderBalance, err := client.BalanceAt(ctx, auth.From, nil) + if err != nil { + return err + } + log.Debugf("ETH Balance for %v: %v", auth.From, senderBalance) + + amount := big.NewInt(10) //nolint:gomnd + log.Debugf("Transfer Amount: %v", amount) + + senderNonce, err := client.PendingNonceAt(ctx, auth.From) + if err != nil { + return err + } + log.Debugf("Sender Nonce: %v", senderNonce) + + to := common.HexToAddress(receiverAddr) + log.Infof("Receiver Addr: %v", to.String()) + + gasLimit, err := client.EstimateGas(ctx, ethereum.CallMsg{From: auth.From, To: &to, Value: amount}) + if err != nil { + return err + } + + gasPrice, err := client.SuggestGasPrice(ctx) + if err != nil { + return err + } + + txs := make([]*types.Transaction, 0, nTxs) + for i := 0; i < nTxs; i++ { + tx := types.NewTransaction(senderNonce+uint64(i), to, amount, gasLimit, gasPrice, nil) + txs = append(txs, tx) + } + + if cliCtx.Bool(flagWaitName) { + var err error + if network.networkLayer == networkLayer1 { + err = operations.ApplyL1Txs(ctx, txs, auth, client) + } else if network.networkLayer == networkLayer2 { + _, err = operations.ApplyL2Txs(ctx, txs, auth, client, operations.VerifiedConfirmationLevel) + } + if err != nil { + return err + } + } else { + for i := 0; i < nTxs; i++ { + signedTx, err := auth.Signer(auth.From, txs[i]) + if err != nil { + return err + } + log.Infof("Sending Tx %v Nonce %v", signedTx.Hash(), signedTx.Nonce()) + err = client.SendTransaction(ctx, signedTx) + if err != nil { + return err + } + } + } + + if nTxs > 1 { + log.Infof("%d transactions successfully sent", nTxs) + } else { + log.Info("transaction successfully sent") + } + } + + return nil +} diff --git a/test/scripts/uniswap/main.go b/test/scripts/uniswap/main.go new file mode 100644 index 0000000000..fe740d532a --- /dev/null +++ b/test/scripts/uniswap/main.go @@ -0,0 +1,277 @@ +package main + +import ( + "context" + "fmt" + "math/big" + "strings" + "time" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/log" + ERC20 "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + WETH "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/WETH" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/core/UniswapV2Factory" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/core/UniswapV2Pair" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/interface/UniswapInterfaceMulticall" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/uniswap/v2/periphery/UniswapV2Router02" + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "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" +) + +const ( + // if you want to test using goerli network + // replace this by your goerli infura url + networkURL = "http://localhost:8123" + // replace this by your account private key + pk = "0xdfd01798f92667dbf91df722434e8fbe96af0211d4d1b82bbbbc8f1def7a814f" + txTimeout = 60 * time.Second +) + +func main() { + ctx := context.Background() + log.Infof("connecting to %v", networkURL) + client, err := ethclient.Dial(networkURL) + chkErr(err) + log.Infof("connected") + chainID, err := client.ChainID(ctx) + chkErr(err) + log.Infof("chainID: %v", chainID) + auth := getAuth(ctx, client, pk) + fmt.Println() + balance, err := client.BalanceAt(ctx, auth.From, nil) + chkErr(err) + log.Debugf("ETH Balance for %v: %v", auth.From, balance) + // Deploy ERC20 Tokens to be swapped + aCoinAddr, aCoin := deployERC20(auth, client, "A COIN", "ACO") + fmt.Println() + bCoinAddr, bCoin := deployERC20(auth, client, "B COIN", "BCO") + fmt.Println() + cCoinAddr, cCoin := deployERC20(auth, client, "C COIN", "CCO") + fmt.Println() + // Deploy wETH Token, it's required by uniswap to swap ETH by tokens + log.Debugf("Deploying wEth SC") + wEthAddr, tx, wethSC, err := WETH.DeployWETH(auth, client) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("wEth SC tx: %v", tx.Hash().Hex()) + log.Debugf("wEth SC addr: %v", wEthAddr.Hex()) + fmt.Println() + // Deploy Uniswap Factory + log.Debugf("Deploying Uniswap Factory") + factoryAddr, tx, factory, err := UniswapV2Factory.DeployUniswapV2Factory(auth, client, auth.From) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("Uniswap Factory SC tx: %v", tx.Hash().Hex()) + log.Debugf("Uniswap Factory SC addr: %v", factoryAddr.Hex()) + fmt.Println() + // Deploy Uniswap Router + log.Debugf("Deploying Uniswap Router") + routerAddr, tx, router, err := UniswapV2Router02.DeployUniswapV2Router02(auth, client, factoryAddr, wEthAddr) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("Uniswap Router SC tx: %v", tx.Hash().Hex()) + log.Debugf("Uniswap Router SC addr: %v", routerAddr.Hex()) + fmt.Println() + // Deploy Uniswap Interface Multicall + log.Debugf("Deploying Uniswap Multicall") + multicallAddr, tx, _, err := UniswapInterfaceMulticall.DeployUniswapInterfaceMulticall(auth, client) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("Uniswap Interface Multicall SC tx: %v", tx.Hash().Hex()) + log.Debugf("Uniswap Interface Multicall SC addr: %v", multicallAddr.Hex()) + fmt.Println() + // Mint balance to tokens + log.Debugf("Minting ERC20 Tokens") + aMintAmount := "1000000000000000000000" + tx = mintERC20(auth, client, aCoin, aMintAmount) + log.Debugf("Mint A Coin tx: %v", tx.Hash().Hex()) + fmt.Println() + bMintAmount := "1000000000000000000000" + tx = mintERC20(auth, client, bCoin, bMintAmount) + log.Debugf("Mint B Coin tx: %v", tx.Hash().Hex()) + fmt.Println() + cMintAmount := "1000000000000000000000" + tx = mintERC20(auth, client, cCoin, cMintAmount) + log.Debugf("Mint C Coin tx: %v", tx.Hash().Hex()) + fmt.Println() + // wrapping eth + wethDepositoAmount := "20000000000000000" + log.Debugf("Depositing %v ETH for account %v on token wEth", wethDepositoAmount, auth.From) + wAuth := getAuth(ctx, client, pk) + wAuth.Value, _ = big.NewInt(0).SetString(wethDepositoAmount, encoding.Base10) + tx, err = wethSC.Deposit(auth) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + value, err := aCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before allowance aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before allowance bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before allowance cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + // Add allowance + approveERC20(auth, client, aCoin, routerAddr, aMintAmount) + fmt.Println() + approveERC20(auth, client, bCoin, routerAddr, bMintAmount) + fmt.Println() + approveERC20(auth, client, cCoin, routerAddr, cMintAmount) + fmt.Println() + approveERC20(auth, client, wethSC, routerAddr, wethDepositoAmount) + fmt.Println() + const liquidityAmount = "10000000000000000000" + value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity A, B aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity A, B bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity A, B cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + // Add liquidity to the pool + tx = addLiquidity(auth, client, router, aCoinAddr, bCoinAddr, liquidityAmount) + log.Debugf("Add Liquidity to Pair A <-> B tx: %v", tx.Hash().Hex()) + fmt.Println() + value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity B, C aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity B, C bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before adding liquidity B, C cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + tx = addLiquidity(auth, client, router, bCoinAddr, cCoinAddr, liquidityAmount) + log.Debugf("Add Liquidity to Pair B <-> C tx: %v", tx.Hash().Hex()) + fmt.Println() + // Execute swaps + const swapExactAmountInNumber = 1000000000000000000 + swapExactAmountIn := big.NewInt(swapExactAmountInNumber) + value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before first swap aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before first swap bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("before first swap cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + log.Debugf("Swaping tokens from A <-> B") + swapExactTokensForTokens(auth, client, factory, router, aCoinAddr, bCoinAddr, swapExactAmountIn) + fmt.Println() + value, err = aCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("after first swap aCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = bCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("after first swap bCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + value, err = cCoin.BalanceOf(&bind.CallOpts{}, auth.From) + chkErr(err) + log.Debugf("after first swap cCoin.balanceOf[%s]: %d", auth.From.Hex(), value) + log.Debugf("Swaping tokens from B <-> C") + swapExactTokensForTokens(auth, client, factory, router, bCoinAddr, cCoinAddr, swapExactAmountIn) + fmt.Println() +} +func swapExactTokensForTokens(auth *bind.TransactOpts, client *ethclient.Client, + factory *UniswapV2Factory.UniswapV2Factory, router *UniswapV2Router02.UniswapV2Router02, + tokenA, tokenB common.Address, exactAmountIn *big.Int) { + ctx := context.Background() + logPrefix := fmt.Sprintf("swapExactTokensForTokens %v <-> %v", tokenA.Hex(), tokenB.Hex()) + pairAddr, err := factory.GetPair(nil, tokenA, tokenB) + chkErr(err) + log.Debug(logPrefix, " pair: ", pairAddr.Hex()) + pairSC, err := UniswapV2Pair.NewUniswapV2Pair(pairAddr, client) + chkErr(err) + pairReserves, err := pairSC.GetReserves(nil) + chkErr(err) + log.Debug(logPrefix, " reserves 0: ", pairReserves.Reserve0, " 1: ", pairReserves.Reserve1, " Block Timestamp: ", pairReserves.BlockTimestampLast) + amountOut, err := router.GetAmountOut(nil, exactAmountIn, pairReserves.Reserve0, pairReserves.Reserve1) + chkErr(err) + log.Debug(logPrefix, " exactAmountIn: ", exactAmountIn, " amountOut: ", amountOut) + tx, err := router.SwapExactTokensForTokens(auth, exactAmountIn, amountOut, []common.Address{tokenA, tokenB}, auth.From, getDeadline()) + chkErr(err) + log.Debug(logPrefix, " tx: ", tx.Hash().Hex()) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) +} +func getAuth(ctx context.Context, client *ethclient.Client, pkHex string) *bind.TransactOpts { + chainID, err := client.ChainID(ctx) + chkErr(err) + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(pkHex, "0x")) + chkErr(err) + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, chainID) + chkErr(err) + return auth +} +func deployERC20(auth *bind.TransactOpts, client *ethclient.Client, name, symbol string) (common.Address, *ERC20.ERC20) { + ctx := context.Background() + log.Debugf("Deploying ERC20 Token: [%v]%v", symbol, name) + addr, tx, instance, err := ERC20.DeployERC20(auth, client, name, symbol) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("%v SC tx: %v", name, tx.Hash().Hex()) + log.Debugf("%v SC addr: %v", name, addr.Hex()) + return addr, instance +} +func mintERC20(auth *bind.TransactOpts, client *ethclient.Client, erc20sc *ERC20.ERC20, amount string) *types.Transaction { + ctx := context.Background() + name, err := erc20sc.Name(nil) + chkErr(err) + log.Debugf("Minting %v tokens for account %v on token %v", amount, auth.From, name) + mintAmount, _ := big.NewInt(0).SetString(amount, encoding.Base10) + tx, err := erc20sc.Mint(auth, mintAmount) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + return tx +} +func approveERC20(auth *bind.TransactOpts, client *ethclient.Client, + sc interface { + Name(opts *bind.CallOpts) (string, error) + Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) + }, + routerAddr common.Address, + amount string) { + ctx := context.Background() + name, err := sc.Name(nil) + chkErr(err) + a, _ := big.NewInt(0).SetString(amount, encoding.Base10) + log.Debugf("Approving %v tokens to be used by the router for %v on behalf of account %v", a.Text(encoding.Base10), name, auth.From) + tx, err := sc.Approve(auth, routerAddr, a) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + log.Debugf("Approval %v tx: %v", name, tx.Hash().Hex()) +} +func addLiquidity(auth *bind.TransactOpts, client *ethclient.Client, router *UniswapV2Router02.UniswapV2Router02, tokenA, tokenB common.Address, amount string) *types.Transaction { + ctx := context.Background() + a, _ := big.NewInt(0).SetString(amount, encoding.Base10) + log.Debugf("Adding liquidity(%v) for tokens A: %v, B:%v, Recipient: %v", amount, tokenA.Hex(), tokenB.Hex(), auth.From.Hex()) + tx, err := router.AddLiquidity(auth, tokenA, tokenB, a, a, a, a, auth.From, getDeadline()) + chkErr(err) + err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) + chkErr(err) + return tx +} +func getDeadline() *big.Int { + const deadLinelimit = 5 * time.Minute + return big.NewInt(time.Now().UTC().Add(deadLinelimit).Unix()) +} +func chkErr(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/test/sequencer.keystore b/test/sequencer.keystore new file mode 100644 index 0000000000..96b662b7eb --- /dev/null +++ b/test/sequencer.keystore @@ -0,0 +1 @@ +{"address":"f39fd6e51aad88f6f4ce6ab8827279cfffb92266","crypto":{"cipher":"aes-128-ctr","ciphertext":"d005030a7684f3adad2447cbb27f63039eec2224c451eaa445de0d90502b9f3d","cipherparams":{"iv":"dc07a54bc7e388efa89c34d42f2ebdb4"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"cf2ec55ecae11171de575112cfb16963570533a9c46fb774473ceb11519eb24a"},"mac":"3eb180d405a5da6e462b2adc00091c14856c91d574bf27348714506357d6e177"},"id":"035454db-6b6d-477f-8a79-ce24c10b185f","version":3} \ No newline at end of file diff --git a/test/testutils/utils.go b/test/testutils/utils.go index d9c8675605..21a321f865 100644 --- a/test/testutils/utils.go +++ b/test/testutils/utils.go @@ -2,12 +2,18 @@ package testutils import ( "fmt" + "io" "os" "path" "runtime" "strings" + "sync" + "testing" + "time" "github.com/0xPolygonHermez/zkevm-node/log" + ioprometheusclient "github.com/prometheus/client_model/go" + "github.com/prometheus/common/expfmt" "github.com/spf13/afero" ) @@ -33,6 +39,16 @@ func CreateTestFiles(appFs afero.Fs, files map[string]string) error { return nil } +// ParseMetricFamilies parsing prometheus response from http endpoint +func ParseMetricFamilies(content io.Reader) (map[string]*ioprometheusclient.MetricFamily, error) { + var parser expfmt.TextParser + mf, err := parser.TextToMetricFamilies(content) + if err != nil { + return nil, err + } + return mf, nil +} + // CheckError checks the given error taking into account if it was expected and // potentially the message it should carry. func CheckError(err error, expected bool, msg string) error { @@ -79,3 +95,20 @@ func GetEnv(key string, defaultValue string) string { } return defaultValue } + +// WaitUntil waits for the given WaitGroup to end. The test fails if the +// WaitGroup is not finished before the provided timeout. +func WaitUntil(t *testing.T, wg *sync.WaitGroup, timeout time.Duration) { + done := make(chan struct{}) + + go func() { + wg.Wait() + close(done) + }() + + select { + case <-done: + case <-time.After(timeout): + t.Fatalf("WaitGroup not done, test time expired after %s", timeout) + } +} diff --git a/test/tracers/tracer.json b/test/tracers/tracer.json index b751e2cc4b..e72f361df9 100644 --- a/test/tracers/tracer.json +++ b/test/tracers/tracer.json @@ -1 +1 @@ -{"tracer":"// tracer allows Geth's `debug_traceTransaction` to mimic the output of Parity's `trace_replayTransaction`\n{\n // The call stack of the EVM execution.\n callStack: [{}],\n\n // step is invoked for every opcode that the VM executes.\n step(log, db) {\n // Capture any errors immediately\n const error = log.getError();\n\n if (error !== undefined) {\n this.fault(log, db);\n } else {\n this.success(log, db);\n }\n },\n\n // fault is invoked when the actual execution of an opcode fails.\n fault(log, db) {\n // If the topmost call already reverted, don't handle the additional fault again\n if (this.topCall().error === undefined) {\n this.putError(log);\n }\n },\n\n putError(log) {\n if (this.callStack.length > 1) {\n this.putErrorInTopCall(log);\n } else {\n this.putErrorInBottomCall(log);\n }\n },\n\n putErrorInTopCall(log) {\n // Pop off the just failed call\n const call = this.callStack.pop();\n this.putErrorInCall(log, call);\n this.pushChildCall(call);\n },\n\n putErrorInBottomCall(log) {\n const call = this.bottomCall();\n this.putErrorInCall(log, call);\n },\n\n putErrorInCall(log, call) {\n call.error = log.getError();\n\n // Consume all available gas and clean any leftovers\n if (call.gasBigInt !== undefined) {\n call.gasUsedBigInt = call.gasBigInt;\n }\n\n delete call.outputOffset;\n delete call.outputLength;\n },\n\n topCall() {\n return this.callStack[this.callStack.length - 1];\n },\n\n bottomCall() {\n return this.callStack[0];\n },\n\n pushChildCall(childCall) {\n const topCall = this.topCall();\n\n if (topCall.calls === undefined) {\n topCall.calls = [];\n }\n\n topCall.calls.push(childCall);\n },\n\n pushGasToTopCall(log) {\n const topCall = this.topCall();\n\n if (topCall.gasBigInt === undefined) {\n topCall.gasBigInt = log.getGas();\n }\n topCall.gasUsedBigInt = topCall.gasBigInt - log.getGas() - log.getCost();\n },\n\n success(log, db) {\n const op = log.op.toString();\n\n this.beforeOp(log, db);\n\n switch (op) {\n case 'CREATE':\n this.createOp(log);\n break;\n case 'CREATE2':\n this.create2Op(log);\n break;\n case 'SELFDESTRUCT':\n this.selfDestructOp(log, db);\n break;\n case 'CALL':\n case 'CALLCODE':\n case 'DELEGATECALL':\n case 'STATICCALL':\n this.callOp(log, op);\n break;\n case 'REVERT':\n this.revertOp();\n break;\n }\n },\n\n beforeOp(log, db) {\n /**\n * Depths\n * 0 - `ctx`. Never shows up in `log.getDepth()`\n * 1 - first level of `log.getDepth()`\n *\n * callStack indexes\n *\n * 0 - pseudo-call stand-in for `ctx` in initializer (`callStack: [{}]`)\n * 1 - first callOp inside of `ctx`\n */\n const logDepth = log.getDepth();\n const callStackDepth = this.callStack.length;\n\n if (logDepth < callStackDepth) {\n // Pop off the last call and get the execution results\n const call = this.callStack.pop();\n\n const ret = log.stack.peek(0);\n\n if (!ret.equals(0)) {\n if (call.type === 'create' || call.type === 'create2') {\n call.createdContractAddressHash = toHex(toAddress(ret.toString(16)));\n call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16))));\n } else {\n call.output = toHex(log.memory.slice(call.outputOffset, call.outputOffset + call.outputLength));\n }\n } else if (call.error === undefined) {\n call.error = 'internal failure';\n }\n\n delete call.outputOffset;\n delete call.outputLength;\n\n this.pushChildCall(call);\n }\n else {\n this.pushGasToTopCall(log);\n }\n },\n\n createOp(log) {\n const inputOffset = log.stack.peek(1).valueOf();\n const inputLength = log.stack.peek(2).valueOf();\n const inputEnd = inputOffset + inputLength;\n const stackValue = log.stack.peek(0);\n\n const call = {\n type: 'create',\n from: toHex(log.contract.getAddress()),\n init: toHex(log.memory.slice(inputOffset, inputEnd)),\n valueBigInt: bigInt(stackValue.toString(10))\n };\n this.callStack.push(call);\n },\n\n create2Op(log) {\n const inputOffset = log.stack.peek(1).valueOf();\n const inputLength = log.stack.peek(2).valueOf();\n const inputEnd = inputOffset + inputLength;\n const stackValue = log.stack.peek(0);\n\n const call = {\n type: 'create2',\n from: toHex(log.contract.getAddress()),\n init: toHex(log.memory.slice(inputOffset, inputEnd)),\n valueBigInt: bigInt(stackValue.toString(10))\n };\n this.callStack.push(call);\n },\n\n selfDestructOp(log, db) {\n const contractAddress = log.contract.getAddress();\n\n this.pushChildCall({\n type: 'selfdestruct',\n from: toHex(contractAddress),\n to: toHex(toAddress(log.stack.peek(0).toString(16))),\n gasBigInt: log.getGas(),\n gasUsedBigInt: log.getCost(),\n valueBigInt: db.getBalance(contractAddress)\n });\n },\n\n callOp(log, op) {\n const to = toAddress(log.stack.peek(1).toString(16));\n\n // Skip any pre-compile invocations, those are just fancy opcodes\n if (!isPrecompiled(to)) {\n this.callCustomOp(log, op, to);\n }\n },\n\n callCustomOp(log, op, to) {\n const stackOffset = (op === 'DELEGATECALL' || op === 'STATICCALL' ? 0 : 1);\n\n const inputOffset = log.stack.peek(2 + stackOffset).valueOf();\n const inputLength = log.stack.peek(3 + stackOffset).valueOf();\n const inputEnd = inputOffset + inputLength;\n\n const call = {\n type: 'call',\n callType: op.toLowerCase(),\n from: toHex(log.contract.getAddress()),\n to: toHex(to),\n input: toHex(log.memory.slice(inputOffset, inputEnd)),\n outputOffset: log.stack.peek(4 + stackOffset).valueOf(),\n outputLength: log.stack.peek(5 + stackOffset).valueOf()\n };\n\n switch (op) {\n case 'CALL':\n case 'CALLCODE':\n call.valueBigInt = bigInt(log.stack.peek(2));\n break;\n case 'DELEGATECALL':\n // value inherited from scope during call sequencing\n break;\n case 'STATICCALL':\n // by definition static calls transfer no value\n call.valueBigInt = bigInt.zero;\n break;\n default:\n throw 'Unknown custom call op ' + op;\n }\n\n this.callStack.push(call);\n },\n\n revertOp() {\n this.topCall().error = 'execution reverted';\n },\n\n // result is invoked when all the opcodes have been iterated over and returns\n // the final result of the tracing.\n result(ctx, db) {\n const result = this.ctxToResult(ctx, db);\n const filtered = this.filterNotUndefined(result);\n const callSequence = this.sequence(filtered, [], filtered.valueBigInt, []).callSequence;\n return this.encodeCallSequence(callSequence);\n },\n\n ctxToResult(ctx, db) {\n var result;\n\n switch (ctx.type) {\n case 'CALL':\n result = this.ctxToCall(ctx);\n break;\n case 'CREATE':\n result = this.ctxToCreate(ctx, db);\n break;\n case 'CREATE2':\n result = this.ctxToCreate2(ctx, db);\n break;\n }\n\n return result;\n },\n\n ctxToCall(ctx) {\n const result = {\n type: 'call',\n callType: 'call',\n from: toHex(ctx.from),\n to: toHex(ctx.to),\n valueBigInt: bigInt(ctx.value.toString(10)),\n gasBigInt: bigInt(ctx.gas),\n gasUsedBigInt: bigInt(ctx.gasUsed),\n input: toHex(ctx.input)\n };\n\n this.putBottomChildCalls(result);\n this.putErrorOrOutput(result, ctx);\n\n return result;\n },\n\n putErrorOrOutput(result, ctx) {\n const error = this.error(ctx);\n\n if (error !== undefined) {\n result.error = error;\n } else {\n result.output = toHex(ctx.output);\n }\n },\n\n ctxToCreate(ctx, db) {\n const result = {\n type: 'create',\n from: toHex(ctx.from),\n init: toHex(ctx.input),\n valueBigInt: bigInt(ctx.value.toString(10)),\n gasBigInt: bigInt(ctx.gas),\n gasUsedBigInt: bigInt(ctx.gasUsed)\n };\n\n this.putBottomChildCalls(result);\n this.putErrorOrCreatedContract(result, ctx, db);\n\n return result;\n },\n\n ctxToCreate2(ctx, db) {\n const result = {\n type: 'create2',\n from: toHex(ctx.from),\n init: toHex(ctx.input),\n valueBigInt: bigInt(ctx.value.toString(10)),\n gasBigInt: bigInt(ctx.gas),\n gasUsedBigInt: bigInt(ctx.gasUsed)\n };\n\n this.putBottomChildCalls(result);\n this.putErrorOrCreatedContract(result, ctx, db);\n\n return result;\n },\n\n putBottomChildCalls(result) {\n const bottomCall = this.bottomCall();\n const bottomChildCalls = bottomCall.calls;\n\n if (bottomChildCalls !== undefined) {\n result.calls = bottomChildCalls;\n }\n },\n\n putErrorOrCreatedContract(result, ctx, db) {\n const error = this.error(ctx);\n\n if (error !== undefined) {\n result.error = error\n } else {\n result.createdContractAddressHash = toHex(ctx.to);\n if (toHex(ctx.input) != '0x') {\n result.createdContractCode = toHex(db.getCode(ctx.to));\n } else {\n result.createdContractCode = '0x';\n }\n }\n },\n\n error(ctx) {\n var error;\n\n const bottomCall = this.bottomCall();\n const bottomCallError = bottomCall.error;\n\n if (bottomCallError !== undefined) {\n error = bottomCallError;\n } else {\n const ctxError = ctx.error;\n\n if (ctxError !== undefined) {\n error = ctxError;\n }\n }\n\n return error;\n },\n\n filterNotUndefined(call) {\n for (var key in call) {\n if (call[key] === undefined) {\n delete call[key];\n }\n }\n\n if (call.calls !== undefined) {\n for (var i = 0; i < call.calls.length; i++) {\n call.calls[i] = this.filterNotUndefined(call.calls[i]);\n }\n }\n\n return call;\n },\n\n // sequence converts the finalized calls from a call tree to a call sequence\n sequence(call, callSequence, availableValueBigInt, traceAddress) {\n const subcalls = call.calls;\n delete call.calls;\n\n call.traceAddress = traceAddress;\n\n if (call.type === 'call' && call.callType === 'delegatecall') {\n call.valueBigInt = availableValueBigInt;\n }\n\n var newCallSequence = callSequence.concat([call]);\n\n if (subcalls !== undefined) {\n for (var i = 0; i < subcalls.length; i++) {\n const nestedSequenced = this.sequence(\n subcalls[i],\n newCallSequence,\n call.valueBigInt,\n traceAddress.concat([i])\n );\n newCallSequence = nestedSequenced.callSequence;\n }\n }\n\n return {\n callSequence: newCallSequence\n };\n },\n\n encodeCallSequence(calls) {\n for (var i = 0; i < calls.length; i++) {\n this.encodeCall(calls[i]);\n }\n\n return calls;\n },\n\n encodeCall(call) {\n this.putValue(call);\n this.putGas(call);\n this.putGasUsed(call);\n\n return call;\n },\n\n putValue(call) {\n const valueBigInt = call.valueBigInt;\n delete call.valueBigInt;\n\n call.value = '0x' + valueBigInt.toString(16);\n },\n\n putGas(call) {\n const gasBigInt = call.gasBigInt;\n delete call.gasBigInt;\n\n if (gasBigInt === undefined) {\n gasBigInt = bigInt.zero;\n }\n\n call.gas = '0x' + gasBigInt.toString(16);\n },\n\n putGasUsed(call) {\n const gasUsedBigInt = call.gasUsedBigInt;\n delete call.gasUsedBigInt;\n\n if (gasUsedBigInt === undefined) {\n gasUsedBigInt = bigInt.zero;\n }\n\n call.gasUsed = '0x' + gasUsedBigInt.toString(16);\n }\n}\n"} \ No newline at end of file +{"tracer":"{ callStack: [ {} ], step(log, db) { const error = log.getError(); if (error !== undefined) { this.fault(log, db); } else { this.success(log, db); } }, fault(log, db) { if (this.topCall().error === undefined) { this.putError(log); } }, putError(log) { if (this.callStack.length > 1) { this.putErrorInTopCall(log); } else { this.putErrorInBottomCall(log); } }, putErrorInTopCall(log) { const call = this.callStack.pop(); this.putErrorInCall(log, call); this.pushChildCall(call); }, putErrorInBottomCall(log) { const call = this.bottomCall(); this.putErrorInCall(log, call); }, putErrorInCall(log, call) { call.error = log.getError(); if (call.gasBigInt !== undefined) { call.gasUsedBigInt = call.gasBigInt; } delete call.outputOffset; delete call.outputLength; }, topCall() { return this.callStack[this.callStack.length - 1 ]; }, bottomCall() { return this.callStack[ 0 ]; }, pushChildCall(childCall) { const topCall = this.topCall(); if (topCall.calls === undefined) { topCall.calls = []; } topCall.calls.push(childCall); }, pushGasToTopCall(log) { const topCall = this.topCall(); if (topCall.gasBigInt === undefined) { topCall.gasBigInt = log.getGas(); } topCall.gasUsedBigInt = topCall.gasBigInt - log.getGas() - log.getCost(); }, success(log, db) { const op = log.op.toString(); this.beforeOp(log, db); switch (op) { case 'CREATE': this.createOp(log); break; case 'CREATE2': this.create2Op(log); break; case 'SELFDESTRUCT': this.selfDestructOp(log, db); break; case 'CALL': case 'CALLCODE': case 'DELEGATECALL': case 'STATICCALL': this.callOp(log, op); break; case 'REVERT': this.revertOp(); break; } }, beforeOp(log, db) { const logDepth = log.getDepth(); const callStackDepth = this.callStack.length; if (logDepth < callStackDepth) { const call = this.callStack.pop(); const ret = log.stack.peek(0); if (!ret.equals(0)) { if (call.type === 'create' || call.type === 'create2') { call.createdContractAddressHash = toHex(toAddress(ret.toString(16))); call.createdContractCode = toHex(db.getCode(toAddress(ret.toString(16)))); } else { call.output = toHex(log.memory.slice(call.outputOffset, call.outputOffset + call.outputLength)); } } else if (call.error === undefined) { call.error = 'internal failure'; } delete call.outputOffset; delete call.outputLength; this.pushChildCall(call); } else { this.pushGasToTopCall(log); } }, createOp(log) { const inputOffset = log.stack.peek(1).valueOf(); const inputLength = log.stack.peek(2).valueOf(); const inputEnd = inputOffset + inputLength; const stackValue = log.stack.peek(0); const call = { type: 'create', from: toHex(log.contract.getAddress()), init: toHex(log.memory.slice(inputOffset, inputEnd)), valueBigInt: bigInt(stackValue.toString(10)) }; this.callStack.push(call); }, create2Op(log) { const inputOffset = log.stack.peek(1).valueOf(); const inputLength = log.stack.peek(2).valueOf(); const inputEnd = inputOffset + inputLength; const stackValue = log.stack.peek(0); const call = { type: 'create2', from: toHex(log.contract.getAddress()), init: toHex(log.memory.slice(inputOffset, inputEnd)), valueBigInt: bigInt(stackValue.toString(10)) }; this.callStack.push(call); }, selfDestructOp(log, db) { const contractAddress = log.contract.getAddress(); this.pushChildCall({ type: 'selfdestruct', from: toHex(contractAddress), to: toHex(toAddress(log.stack.peek(0).toString(16))), gasBigInt: log.getGas(), gasUsedBigInt: log.getCost(), valueBigInt: db.getBalance(contractAddress) }); }, callOp(log, op) { const to = toAddress(log.stack.peek(1).toString(16)); if (!isPrecompiled(to)) { this.callCustomOp(log, op, to); } }, callCustomOp(log, op, to) { const stackOffset = (op === 'DELEGATECALL' || op === 'STATICCALL' ? 0 : 1); const inputOffset = log.stack.peek(2 + stackOffset).valueOf(); const inputLength = log.stack.peek(3 + stackOffset).valueOf(); const inputEnd = inputOffset + inputLength; const call = { type: 'call', callType: op.toLowerCase(), from: toHex(log.contract.getAddress()), to: toHex(to), input: toHex(log.memory.slice(inputOffset, inputEnd)), outputOffset: log.stack.peek(4 + stackOffset).valueOf(), outputLength: log.stack.peek(5 + stackOffset).valueOf() }; switch (op) { case 'CALL': case 'CALLCODE': call.valueBigInt = bigInt(log.stack.peek(2)); break; case 'DELEGATECALL': break; case 'STATICCALL': call.valueBigInt = bigInt.zero; break; default: throw 'Unknown custom call op ' + op; } this.callStack.push(call); }, revertOp() { this.topCall().error = 'execution reverted'; }, result(ctx, db) { const result = this.ctxToResult(ctx, db); const filtered = this.filterNotUndefined(result); const callSequence = this.sequence(filtered, [], filtered.valueBigInt, []).callSequence; return this.encodeCallSequence(callSequence); }, ctxToResult(ctx, db) { var result; switch (ctx.type) { case 'CALL': result = this.ctxToCall(ctx); break; case 'CREATE': result = this.ctxToCreate(ctx, db); break; case 'CREATE2': result = this.ctxToCreate2(ctx, db); break; } return result; }, ctxToCall(ctx) { const result = { type: 'call', callType: 'call', from: toHex(ctx.from), to: toHex(ctx.to), valueBigInt: bigInt(ctx.value.toString(10)), gasBigInt: bigInt(ctx.gas), gasUsedBigInt: bigInt(ctx.gasUsed), input: toHex(ctx.input) }; this.putBottomChildCalls(result); this.putErrorOrOutput(result, ctx); return result; }, putErrorOrOutput(result, ctx) { const error = this.error(ctx); if (error !== undefined) { result.error = error; } else { result.output = toHex(ctx.output); } }, ctxToCreate(ctx, db) { const result = { type: 'create', from: toHex(ctx.from), init: toHex(ctx.input), valueBigInt: bigInt(ctx.value.toString(10)), gasBigInt: bigInt(ctx.gas), gasUsedBigInt: bigInt(ctx.gasUsed) }; this.putBottomChildCalls(result); this.putErrorOrCreatedContract(result, ctx, db); return result; }, ctxToCreate2(ctx, db) { const result = { type: 'create2', from: toHex(ctx.from), init: toHex(ctx.input), valueBigInt: bigInt(ctx.value.toString(10)), gasBigInt: bigInt(ctx.gas), gasUsedBigInt: bigInt(ctx.gasUsed) }; this.putBottomChildCalls(result); this.putErrorOrCreatedContract(result, ctx, db); return result; }, putBottomChildCalls(result) { const bottomCall = this.bottomCall(); const bottomChildCalls = bottomCall.calls; if (bottomChildCalls !== undefined) { result.calls = bottomChildCalls; } }, putErrorOrCreatedContract(result, ctx, db) { const error = this.error(ctx); if (error !== undefined) { result.error = error } else { result.createdContractAddressHash = toHex(ctx.to); if (toHex(ctx.input) != '0x') { result.createdContractCode = toHex(db.getCode(ctx.to)); } else { result.createdContractCode = '0x'; } } }, error(ctx) { var error; const bottomCall = this.bottomCall(); const bottomCallError = bottomCall.error; if (bottomCallError !== undefined) { error = bottomCallError; } else { const ctxError = ctx.error; if (ctxError !== undefined) { error = ctxError; } } return error; }, filterNotUndefined(call) { for (var key in call) { if (call[key ] === undefined) { delete call[key ]; } } if (call.calls !== undefined) { for (var i = 0; i < call.calls.length; i++) { call.calls[i ] = this.filterNotUndefined(call.calls[i ]); } } return call; }, sequence(call, callSequence, availableValueBigInt, traceAddress) { const subcalls = call.calls; delete call.calls; call.traceAddress = traceAddress; if (call.type === 'call' && call.callType === 'delegatecall') { call.valueBigInt = availableValueBigInt; } var newCallSequence = callSequence.concat([call ]); if (subcalls !== undefined) { for (var i = 0; i < subcalls.length; i++) { const nestedSequenced = this.sequence( subcalls[i ], newCallSequence, call.valueBigInt, traceAddress.concat([i ]) ); newCallSequence = nestedSequenced.callSequence; } } return { callSequence: newCallSequence }; }, encodeCallSequence(calls) { for (var i = 0; i < calls.length; i++) { this.encodeCall(calls[i ]); } return calls; }, encodeCall(call) { this.putValue(call); this.putGas(call); this.putGasUsed(call); return call; }, putValue(call) { const valueBigInt = call.valueBigInt; delete call.valueBigInt; call.value = '0x' + valueBigInt.toString(16); }, putGas(call) { if (call.gasBigInt === undefined) { call.gas = '0x0'; } else { call.gas = '0x' + call.gasBigInt.toString(16); } delete call.gasBigInt; }, putGasUsed(call) { if (call.gasUsedBigInt === undefined) { call.gasUsed = '0x0'; } else { call.gasUsed = '0x' + call.gasUsedBigInt.toString(16); } delete call.gasUsedBigInt; } }"} \ No newline at end of file diff --git a/test/vectors/smartcontract.go b/test/vectors/smartcontract.go index 6ae71e181c..e2a2ce263b 100644 --- a/test/vectors/smartcontract.go +++ b/test/vectors/smartcontract.go @@ -2,7 +2,7 @@ package vectors import ( "encoding/json" - "io/ioutil" + "io" "os" "path/filepath" ) @@ -17,7 +17,7 @@ func LoadTxEventsSendBatchTestCases(path string) ([]TxEventsSendBatchTestCase, e } defer func() { _ = jsonFile.Close() }() - bytes, err := ioutil.ReadAll(jsonFile) + bytes, err := io.ReadAll(jsonFile) if err != nil { return testCases, err } diff --git a/test/vectors/src/state-transition/forced-tx/erc20_0.json b/test/vectors/src/state-transition/forced-tx/erc20_0.json new file mode 100644 index 0000000000..9d2fcd2963 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/erc20_0.json @@ -0,0 +1,484 @@ +{ + "expectedOldStateRoot": "0x0a4f8fc6b826cbce9db13878aab80cf3dda37f5c2f1e241838a0f659cbfbc115", + "expectedNewStateRoot": "0x9e238c1f617d23cfd72449ed2d9a45dc4c0be90c6e01eb8dc37838b9ed2430aa", + "batchL2Data": "0xf86b80843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b84440c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff000000000000000000000000000000000000000000000000000000174876e8008203e98080a612e30f4d945299a49d441ac6f3b0359e2e25f4e8db1e0de0875fd6b6e9acbe04fef9c114fd7baade904c4ea375c46c6cd51eaaafd881dfabf37b1f775f22b51bf86b01843b9aca01830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b84440c10f19000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d000000000000000000000000000000000000000000000000000000174876e8008203e98080d9c40ad6b194ea381c84f474dfde634adb4d15f94d7795ac033b98bf3358c2d32d45ed551dcfd474866a8d35c4caf396ce902a845b79544ba08f3cf80f63fc071bf86b80843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b844a9059cbb000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d00000000000000000000000000000000000000000000000000000000000000648203e980806d69ec926907c4337b2f4f50f412950bb44d20e5ba5efc871aa86c49c57ef42d62c79826b7934a0359accc3bf0dcd8842732cb2372c94b26a13a6e0b742d96f11cf86b02843b9aca02830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b844095ea7b30000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000002540be4008203e980806a8863c18274065bb6c4d00828118ad2d67edf60a5e3eac0c44cc57e4f2b6d9a0df9321416a1af80e08182137cfbc104a48d120738dcb0105b18d2e0e4093e841bf84a01843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880a440b8405a000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d8203e980802df5c4e799cc112d9393c3ed612c22ad5475e6f9cfbfc82749f301f1be35406835da6d34cf9c00e4baf10d1df3e843fdc598bf7878230d8948b7f9ef05c7345e1cf88b02843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b86423b872dd000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d0000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000000000003208203e9808021b6205ae35c5f057814509e7a3ad802414fbf76288a1d9dc56853bc6e9aeb370fde1a2697db9b6426108f6d955b00d726eb69702b772c6bcf4e5713c6d69bbb1bf84a03843b9aca00830186a0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880a440b8405a000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d8203e98080b268eaaecd44392536534ae936102b6ed50c751844f551721993c765c63ac7545d5a94e7ee10a659626d688afaac7f438f84058512442627bf3d35b9633126221c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x48455a0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x48455a0000000000000000000000000000000000000000000000000000000006" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806370a08231116100ad57806395d89b411161007157806395d89b41146102fa578063a457c2d714610318578063a9059cbb14610348578063dd62ed3e14610378578063f2fde38b146103a857610121565b806370a082311461027a578063715018a6146102aa5780637d64bcb4146102b45780638da5cb5b146102be5780638f1c56bd146102dc57610121565b806323b872dd116100f457806323b872dd146101b0578063313ce567146101e057806339509351146101fe57806340b8405a1461022e57806340c10f191461025e57610121565b806305d2035b1461012657806306fdde0314610144578063095ea7b31461016257806318160ddd14610192575b600080fd5b61012e6103c4565b60405161013b919061186f565b60405180910390f35b61014c6103db565b604051610159919061188a565b60405180910390f35b61017c60048036038101906101779190611664565b61046d565b604051610189919061186f565b60405180910390f35b61019a61048b565b6040516101a791906119cc565b60405180910390f35b6101ca60048036038101906101c59190611611565b610495565b6040516101d7919061186f565b60405180910390f35b6101e861056e565b6040516101f591906119e7565b60405180910390f35b61021860048036038101906102139190611664565b610585565b604051610225919061186f565b60405180910390f35b610248600480360381019061024391906115a4565b610638565b60405161025591906119cc565b60405180910390f35b61027860048036038101906102739190611664565b6106c5565b005b610294600480360381019061028f91906115a4565b610723565b6040516102a191906119cc565b60405180910390f35b6102b261076b565b005b6102bc6108c3565b005b6102c661091d565b6040516102d39190611854565b60405180910390f35b6102e4610947565b6040516102f191906119cc565b60405180910390f35b61030261094d565b60405161030f919061188a565b60405180910390f35b610332600480360381019061032d9190611664565b6109df565b60405161033f919061186f565b60405180910390f35b610362600480360381019061035d9190611664565b610aac565b60405161036f919061186f565b60405180910390f35b610392600480360381019061038d91906115d1565b610aca565b60405161039f91906119cc565b60405180910390f35b6103c260048036038101906103bd91906115a4565b610b51565b005b6000600760009054906101000a900460ff16905090565b6060600380546103ea90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461041690611b30565b80156104635780601f1061043857610100808354040283529160200191610463565b820191906000526020600020905b81548152906001019060200180831161044657829003601f168201915b5050505050905090565b600061048161047a610d18565b8484610d20565b6001905092915050565b6000600254905090565b60006104a2848484610eeb565b610563846104ae610d18565b61055e85604051806060016040528060288152602001611e8060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610514610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b600190509392505050565b6000600560009054906101000a900460ff16905090565b600061062e610592610d18565b8461062985600160006105a3610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b610d20565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546006819055506000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600760009054906101000a900460ff1615610715576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161070c9061198c565b60405180910390fd5b61071f8282611242565b5050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610773610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f99061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600760009054906101000a900460ff1615610913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090a9061198c565b60405180910390fd5b61091b6112e7565b565b6000600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60606004805461095c90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461098890611b30565b80156109d55780601f106109aa576101008083540402835291602001916109d5565b820191906000526020600020905b8154815290600101906020018083116109b857829003601f168201915b5050505050905090565b6000610aa26109ec610d18565b84610a9d85604051806060016040528060258152602001611ea86025913960016000610a16610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b6001905092915050565b6000610ac0610ab9610d18565b8484610eeb565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610b59610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610be8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdf9061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610c58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4f906118cc565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610d90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d879061196c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df7906118ec565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610ede91906119cc565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061194c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc2906118ac565b60405180910390fd5b610fd6838383611388565b61104181604051806060016040528060268152602001611e5a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110d4816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161117391906119cc565b60405180910390a3505050565b60008383111582906111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf919061188a565b60405180910390fd5b50600083856111d79190611a74565b9050809150509392505050565b60008082846111f39190611a1e565b905083811015611238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122f9061190c565b60405180910390fd5b8091505092915050565b61124a610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d09061192c565b60405180910390fd5b6112e38282611398565b5050565b6112ef610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461137e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113759061192c565b60405180910390fd5b61138661152c565b565b611393838383611575565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611408576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ff906119ac565b60405180910390fd5b61141460008383611388565b611429816002546111e490919063ffffffff16565b600281905550611480816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161152091906119cc565b60405180910390a35050565b6001600760006101000a81548160ff0219169083151502179055507fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0860405160405180910390a1565b505050565b60008135905061158981611e2b565b92915050565b60008135905061159e81611e42565b92915050565b6000602082840312156115ba576115b9611bc0565b5b60006115c88482850161157a565b91505092915050565b600080604083850312156115e8576115e7611bc0565b5b60006115f68582860161157a565b92505060206116078582860161157a565b9150509250929050565b60008060006060848603121561162a57611629611bc0565b5b60006116388682870161157a565b93505060206116498682870161157a565b925050604061165a8682870161158f565b9150509250925092565b6000806040838503121561167b5761167a611bc0565b5b60006116898582860161157a565b925050602061169a8582860161158f565b9150509250929050565b6116ad81611aa8565b82525050565b6116bc81611aba565b82525050565b60006116cd82611a02565b6116d78185611a0d565b93506116e7818560208601611afd565b6116f081611bc5565b840191505092915050565b6000611708602383611a0d565b915061171382611bd6565b604082019050919050565b600061172b602683611a0d565b915061173682611c25565b604082019050919050565b600061174e602283611a0d565b915061175982611c74565b604082019050919050565b6000611771601b83611a0d565b915061177c82611cc3565b602082019050919050565b6000611794602083611a0d565b915061179f82611cec565b602082019050919050565b60006117b7602583611a0d565b91506117c282611d15565b604082019050919050565b60006117da602483611a0d565b91506117e582611d64565b604082019050919050565b60006117fd602283611a0d565b915061180882611db3565b604082019050919050565b6000611820601f83611a0d565b915061182b82611e02565b602082019050919050565b61183f81611ae6565b82525050565b61184e81611af0565b82525050565b600060208201905061186960008301846116a4565b92915050565b600060208201905061188460008301846116b3565b92915050565b600060208201905081810360008301526118a481846116c2565b905092915050565b600060208201905081810360008301526118c5816116fb565b9050919050565b600060208201905081810360008301526118e58161171e565b9050919050565b6000602082019050818103600083015261190581611741565b9050919050565b6000602082019050818103600083015261192581611764565b9050919050565b6000602082019050818103600083015261194581611787565b9050919050565b60006020820190508181036000830152611965816117aa565b9050919050565b60006020820190508181036000830152611985816117cd565b9050919050565b600060208201905081810360008301526119a5816117f0565b9050919050565b600060208201905081810360008301526119c581611813565b9050919050565b60006020820190506119e16000830184611836565b92915050565b60006020820190506119fc6000830184611845565b92915050565b600081519050919050565b600082825260208201905092915050565b6000611a2982611ae6565b9150611a3483611ae6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115611a6957611a68611b62565b5b828201905092915050565b6000611a7f82611ae6565b9150611a8a83611ae6565b925082821015611a9d57611a9c611b62565b5b828203905092915050565b6000611ab382611ac6565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015611b1b578082015181840152602081019050611b00565b83811115611b2a576000848401525b50505050565b60006002820490506001821680611b4857607f821691505b60208210811415611b5c57611b5b611b91565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600080fd5b6000601f19601f8301169050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f45524332304d696e7461626c653a206d696e74696e672069732066696e69736860008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b611e3481611aa8565b8114611e3f57600080fd5b50565b611e4b81611ae6565b8114611e5657600080fd5b5056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122011d6aa32a52f13724439331c99d3ab1777561b1fe5e60286e4c692fe36f90b1064736f6c63430008070033", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event" + }, + { + "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": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finishMinting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "updateBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "3", + "balance": "99999826395999851395", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "4", + "balance": "199999843965000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0xa26ead204fbe342827d421c1dbb94371b0c0824f05bddc9763f28c44870f2530": "0x02540be0e0", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x2e90edd000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x174876e544", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x5c9164227e4e2850b9fc759a61468f2c11426c1144a6df87b4a501cc3915e91d": "0x174876eabc", + "0x5eff3f6834f82409f2dbfe5bcddfb5bd62b8ea2ebf2327cfdb9577734aa9a1b2": "0x174876e544", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x48455a0000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x48455a0000000000000000000000000000000000000000000000000000000006" + }, + "isSmartContract": true, + "hashBytecode": "0x6a4f4d0553421e715aade51ef1754586485a905fd5826768bc7952704a04c4ba", + "bytecodeLength": 7938 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/eth-CallEcrecoverInvalidSignature.json b/test/vectors/src/state-transition/forced-tx/eth-CallEcrecoverInvalidSignature.json new file mode 100644 index 0000000000..b5ef138363 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/eth-CallEcrecoverInvalidSignature.json @@ -0,0 +1,53 @@ +{ + "expectedOldStateRoot": "0xf630466903d09e625dc648162a469fcfcc6388ba85167b67c2a4a92ca499b72e", + "expectedNewStateRoot": "0x493022ec5de1b00e02816e8ca1275f9527213c21a43ee60aecf6684e19213395", + "batchL2Data": "0xe5800a8337ba9094095e7baea6a6c7c4c2dfeb977efac326af552d87830186a0808203e980806debf9b2a0bf48159a6369cc3aa6f12dbab894abf92645740360048d1a3c3d7d34b0753b0d9c36fdfd7880add1f74e76e4ddce8aad951bca68b6f6680cce18f61c", + "genesis": [ + { + "address": "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", + "nonce": "0", + "balance": "20000000", + "storage": {}, + "isSmartContract": true, + "bytecode": "0x7f1122334455667788991011121314151617181920212223242526272829303132608052602060806080600060006001620493e0f15060805160005500", + "hashBytecode": "0x0a5eeb8d8d1251c076368ce61bee4ec42cfd6d4e1cb9ce1899a9ed6fa4d9ccfc" + }, + { + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "nonce": "0", + "balance": "1000000000000000000", + "storage": {}, + "isSmartContract": false, + "bytecode": "0x" + } + ], + "expectedNewLeafs": [ + { + "address": "0x095e7baea6a6c7c4c2dfeb977efac326af552d87", + "nonce": "0", + "balance": "20100000", + "storage": { + "0x00": "0x1122334455667788991011121314151617181920212223242526272829303132" + }, + "isSmartContract": true, + "bytecode": "0x7f1122334455667788991011121314151617181920212223242526272829303132608052602060806080600060006001620493e0f15060805160005500", + "hashBytecode": "0x0a5eeb8d8d1251c076368ce61bee4ec42cfd6d4e1cb9ce1899a9ed6fa4d9ccfc" + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "462560", + "storage": {}, + "isSmartContract": false, + "bytecode": "0x" + }, + { + "address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "nonce": "1", + "balance": "999999999999437440", + "storage": {}, + "isSmartContract": false, + "bytecode": "0x" + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_0.json b/test/vectors/src/state-transition/forced-tx/general_0.json new file mode 100644 index 0000000000..b0041e26ac --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_0.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x1e67d1a0d39579ea7f16bc520e90a503daea9f7a1a43670dbb1911dbea9c6df1", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980801186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb9700910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c012259687999074321b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "1", + "balance": "99899979000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200100000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "21000000000000", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_1.json b/test/vectors/src/state-transition/forced-tx/general_1.json new file mode 100644 index 0000000000..95df0b93be --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_1.json @@ -0,0 +1,80 @@ +{ + "expectedOldStateRoot": "0x76b362a9afd679ea13a456ab103786492c65946be653589c1fd627841d0c6fdd", + "expectedNewStateRoot": "0x44a9059da9c0866cbafdd492aefeb371836f29eff8c66eb9c2252b5d59bffd25", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980801186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb9700910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c012259687999074321bef80843b9aca00830186a094187bd40226a7073b49163b1f6c2b73d8f2aa8478893635c9adc5dea00000808203e980804c4fbe884ee8912360f4d00199fd189f11b27fa25eca1b9dcfd3ea686e88042e113432240c9e7be8de1e8fc0894b68ff4d37528d820814527b5fa2bd034ef38f1bee80843b9aca00830186a094187bd40226a7073b49163b1f6c2b73d8f2aa8478880de0b6b3a7640000808203e980801cdcd319a4929aca6fc2eeac030635f057c1a9eb3931225b3de5613cc3d78b9c1cf4de1b8d0dc0ab31f9918bca9d308cbff8ac2307b4aa061fe3f4532edad30d1bee80843b9aca00830186a094abcced19d7f290b84608fec510bee872cc8f5112880de0b6b3a7640000808203e98080980717290b2314a735dc00db207c20d5a6461f73761c2022986fd78efa7e774d57de08eada05ec67eb78cceaa7be257cb12b5449aa0d7347dca655f94375c9671bee80843b9aca00830186a094abcced19d7f290b84608fec510bee872cc8f5112880de0b6b3a764000080820d058080d78fe650ae7e2f7c909ad72f661bfe72aa2d502f9f2bbfad3880a4a7e0abf8986b98f2a902dd06a89f948baa64f32d301d3ced92d231ccdea79f909a73aa050f1b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + }, + { + "address": "0xeB17ce701E9D92724AA2ABAdA7E4B28830597Dd9", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x1d0722aff4b29780e9a78e0bf28d5e127fb276cfbb0c3eb6a0e1728401777f17", + "isSmartContract": false + }, + { + "address": "0x187Bd40226A7073b49163b1f6c2b73d8F2aa8478", + "nonce": "0", + "balance": "0", + "pvtKey": "0xd049e68efa0d85a3824c0b79f6817a986bb0cb3a075bcc2699118eca881d70ce", + "isSmartContract": false + }, + { + "address": "0xabCcEd19d7f290B84608feC510bEe872CC8F5112", + "nonce": "0", + "balance": "0", + "pvtKey": "0x0b929d50d7fda8155539e6befa96ff297e3e9ebce4d908f570310bdf774cb32b", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "1", + "balance": "99899979000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200100000000000000000", + "isSmartContract": false + }, + { + "address": "0xeB17ce701E9D92724AA2ABAdA7E4B28830597Dd9", + "nonce": "1", + "balance": "98999979000000000000", + "isSmartContract": false + }, + { + "address": "0x187Bd40226A7073b49163b1f6c2b73d8F2aa8478", + "nonce": "0", + "balance": "1000000000000000000", + "isSmartContract": false + }, + { + "address": "0xabCcEd19d7f290B84608feC510bEe872CC8F5112", + "nonce": "0", + "balance": "0", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "42000000000000", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_2.json b/test/vectors/src/state-transition/forced-tx/general_2.json new file mode 100644 index 0000000000..467cdb4ab2 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_2.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xcc651274e1060f11e5ed7235aad30a6cc5a96d6ccd71d71725eaa2bbb9fc08f8", + "batchL2Data": "0xf080843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8a021e19e0c9bab2400000808203e98080510a8a10721e65bf2913889751f3b32de1cb4733a667e06b708f122965da598e75ca7d27cb4c3846490b4c446605d0120b0720b70dfe5a07f865a161c37263221b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "0", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_3.json b/test/vectors/src/state-transition/forced-tx/general_3.json new file mode 100644 index 0000000000..51d5e5a51e --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_3.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xcc651274e1060f11e5ed7235aad30a6cc5a96d6ccd71d71725eaa2bbb9fc08f8", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a00008082019180806e209c61ca92c2b980d6197e7ac9ccc3f547bf13be6455dfe682aa5dda9655ef16819a7edcc3fefec81ca97c7a6f3d10ec774440e409adbba693ce8b698d41f11cef80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff89056bc75e2d63100000808203e98080fe1e96b35c836fbebac887681150c5fc9fdae862d747aaaf8c30373c0becf7691ff0c900aaaac6d1565a603f69b5a45f222ed205f0a36fdc6e4e4c5a7b88d45b1b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "0", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_4.json b/test/vectors/src/state-transition/forced-tx/general_4.json new file mode 100644 index 0000000000..68de9a4d3f --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_4.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xcc651274e1060f11e5ed7235aad30a6cc5a96d6ccd71d71725eaa2bbb9fc08f8", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980801186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb9719683074bcc81dba07fad2ac4015cf2eba4807c1aa1a8d291e77317a45fc20231b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "0", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_5.json b/test/vectors/src/state-transition/forced-tx/general_5.json new file mode 100644 index 0000000000..9a2bb6ac46 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_5.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x7d132db5b2509e925565da8ed09fedc3028465031435cb3d6c9bb87982e497fe", + "batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980801186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb9700910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c012259687999074321bee01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e98080b09a953b4dccf40c7333ed1a1df6fda10a18d01d7c4320b05f7680b34837b3bd421af00d0c99bb1b4d346d99f3634f46fba700dbc57908d3bfa647cbfbcb81a31cee02843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e980807d6892a0b642053f641a040c5ba59132983cb41af9887cf01f5b132313d68d0f3c77a17d738c8d850a27fe7276b2c73e006b0e52938d960d7b6931dff1f49c971c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "3", + "balance": "99699937000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200300000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "63000000000000", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_6.json b/test/vectors/src/state-transition/forced-tx/general_6.json new file mode 100644 index 0000000000..b388171e23 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_6.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xcc651274e1060f11e5ed7235aad30a6cc5a96d6ccd71d71725eaa2bbb9fc08f8", + "batchL2Data": "0xf080843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8a021e19e0c9bab2400000808203e98080510a8a10721e65bf2913889751f3b32de1cb4733a667e06b708f122965da598e75ca7d27cb4c3846490b4c446605d0120b0720b70dfe5a07f865a161c37263221bf080843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8a021e19e0c9bab2400000808203e98080510a8a10721e65bf2913889751f3b32de1cb4733a667e06b708f122965da598e75ca7d27cb4c3846490b4c446605d0120b0720b70dfe5a07f865a161c37263221bf080843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8a021e19e0c9bab2400000808203e98080510a8a10721e65bf2913889751f3b32de1cb4733a667e06b708f122965da598e75ca7d27cb4c3846490b4c446605d0120b0720b70dfe5a07f865a161c37263221b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "0", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/general_7.json b/test/vectors/src/state-transition/forced-tx/general_7.json new file mode 100644 index 0000000000..55c7a52ee5 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/general_7.json @@ -0,0 +1,41 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xcc651274e1060f11e5ed7235aad30a6cc5a96d6ccd71d71725eaa2bbb9fc08f8", + "batchL2Data": "0x", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "isSmartContract": false + }, + { + "address": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "nonce": "0", + "balance": "0", + "isSmartContract": false + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/mynft_0.json b/test/vectors/src/state-transition/forced-tx/mynft_0.json new file mode 100644 index 0000000000..aecb581fed --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/mynft_0.json @@ -0,0 +1,483 @@ +{ + "expectedOldStateRoot": "0x3ad14bb39c4e9b6f2c1dd2901057e6ef8a3bbb23f6b5589d97f1fa949df5cebd", + "expectedNewStateRoot": "0x2b90f607f563cd36c1574daeedc632f5ef36dcea8b26ff2f021b5bf10a95e927", + "batchL2Data": "0xf8ab80843b9aca00830249f0941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b884eacabe14000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000375726900000000000000000000000000000000000000000000000000000000008203e980806b5b5346d51deb488f85cdee036ac2c09d9ce735725eea0f0a1bdf5eb366caa47934d76d85914ea13a15577d18550e207eae1d43ca5ed58be0ca74f0748d69911b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x4d794e465400000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x4e46540000000000000000000000000000000000000000000000000000000006" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c8063715018a6116100a2578063b88d4fde11610071578063b88d4fde146102a4578063c87b56dd146102c0578063e985e9c5146102f0578063eacabe1414610320578063f2fde38b146103505761010b565b8063715018a6146102425780638da5cb5b1461024c57806395d89b411461026a578063a22cb465146102885761010b565b806323b872dd116100de57806323b872dd146101aa57806342842e0e146101c65780636352211e146101e257806370a08231146102125761010b565b806301ffc9a71461011057806306fdde0314610140578063081812fc1461015e578063095ea7b31461018e575b600080fd5b61012a60048036038101906101259190611f71565b61036c565b604051610137919061233d565b60405180910390f35b61014861044e565b6040516101559190612358565b60405180910390f35b61017860048036038101906101739190611fcb565b6104e0565b60405161018591906122d6565b60405180910390f35b6101a860048036038101906101a39190611f31565b610526565b005b6101c460048036038101906101bf9190611dbf565b61063e565b005b6101e060048036038101906101db9190611dbf565b61069e565b005b6101fc60048036038101906101f79190611fcb565b6106be565b60405161020991906122d6565b60405180910390f35b61022c60048036038101906102279190611d52565b610745565b604051610239919061253a565b60405180910390f35b61024a6107fd565b005b610254610811565b60405161026191906122d6565b60405180910390f35b61027261083b565b60405161027f9190612358565b60405180910390f35b6102a2600480360381019061029d9190611e95565b6108cd565b005b6102be60048036038101906102b99190611e12565b6108e3565b005b6102da60048036038101906102d59190611fcb565b610945565b6040516102e79190612358565b60405180910390f35b61030a60048036038101906103059190611d7f565b610a58565b604051610317919061233d565b60405180910390f35b61033a60048036038101906103359190611ed5565b610aec565b604051610347919061253a565b60405180910390f35b61036a60048036038101906103659190611d52565b610b2c565b005b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061043757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610447575061044682610bb0565b5b9050919050565b60606000805461045d906126d5565b80601f0160208091040260200160405190810160405280929190818152602001828054610489906126d5565b80156104d65780601f106104ab576101008083540402835291602001916104d6565b820191906000526020600020905b8154815290600101906020018083116104b957829003601f168201915b5050505050905090565b60006104eb82610c1a565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610531826106be565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610599906124fa565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166105c1610c65565b73ffffffffffffffffffffffffffffffffffffffff1614806105f057506105ef816105ea610c65565b610a58565b5b61062f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106269061251a565b60405180910390fd5b6106398383610c6d565b505050565b61064f610649610c65565b82610d26565b61068e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106859061237a565b60405180910390fd5b610699838383610dbb565b505050565b6106b9838383604051806020016040528060008152506108e3565b505050565b6000806106ca836110b5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561073c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610733906124da565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107ad9061245a565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6108056110f2565b61080f6000611170565b565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606001805461084a906126d5565b80601f0160208091040260200160405190810160405280929190818152602001828054610876906126d5565b80156108c35780601f10610898576101008083540402835291602001916108c3565b820191906000526020600020905b8154815290600101906020018083116108a657829003601f168201915b5050505050905090565b6108df6108d8610c65565b8383611236565b5050565b6108f46108ee610c65565b83610d26565b610933576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092a9061237a565b60405180910390fd5b61093f848484846113a3565b50505050565b606061095082610c1a565b6000600660008481526020019081526020016000208054610970906126d5565b80601f016020809104026020016040519081016040528092919081815260200182805461099c906126d5565b80156109e95780601f106109be576101008083540402835291602001916109e9565b820191906000526020600020905b8154815290600101906020018083116109cc57829003601f168201915b5050505050905060006109fa6113ff565b9050600081511415610a10578192505050610a53565b600082511115610a45578082604051602001610a2d9291906122b2565b60405160208183030381529060405292505050610a53565b610a4e84611416565b925050505b919050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000610af66110f2565b610b00600861147e565b6000610b0c6008611494565b9050610b1884826114a2565b610b2281846116c0565b8091505092915050565b610b346110f2565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ba4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9b906123ba565b60405180910390fd5b610bad81611170565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b610c2381611734565b610c62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c59906124da565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16610ce0836106be565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610d32836106be565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610d745750610d738185610a58565b5b80610db257508373ffffffffffffffffffffffffffffffffffffffff16610d9a846104e0565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16610ddb826106be565b73ffffffffffffffffffffffffffffffffffffffff1614610e31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e28906123da565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e989061241a565b60405180910390fd5b610eae8383836001611775565b8273ffffffffffffffffffffffffffffffffffffffff16610ece826106be565b73ffffffffffffffffffffffffffffffffffffffff1614610f24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f1b906123da565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46110b0838383600161177b565b505050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6110fa610c65565b73ffffffffffffffffffffffffffffffffffffffff16611118610811565b73ffffffffffffffffffffffffffffffffffffffff161461116e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611165906124ba565b60405180910390fd5b565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156112a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129c9061243a565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611396919061233d565b60405180910390a3505050565b6113ae848484610dbb565b6113ba84848484611781565b6113f9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113f09061239a565b60405180910390fd5b50505050565b606060405180602001604052806000815250905090565b606061142182610c1a565b600061142b6113ff565b9050600081511161144b5760405180602001604052806000815250611476565b8061145584611918565b6040516020016114669291906122b2565b6040516020818303038152906040525b915050919050565b6001816000016000828254019250508190555050565b600081600001549050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611512576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115099061249a565b60405180910390fd5b61151b81611734565b1561155b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611552906123fa565b60405180910390fd5b611569600083836001611775565b61157281611734565b156115b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a9906123fa565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46116bc60008383600161177b565b5050565b6116c982611734565b611708576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ff9061247a565b60405180910390fd5b8060066000848152602001908152602001600020908051906020019061172f929190611b66565b505050565b60008073ffffffffffffffffffffffffffffffffffffffff16611756836110b5565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b50505050565b50505050565b60006117a28473ffffffffffffffffffffffffffffffffffffffff166119f0565b1561190b578373ffffffffffffffffffffffffffffffffffffffff1663150b7a026117cb610c65565b8786866040518563ffffffff1660e01b81526004016117ed94939291906122f1565b602060405180830381600087803b15801561180757600080fd5b505af192505050801561183857506040513d601f19601f820116820180604052508101906118359190611f9e565b60015b6118bb573d8060008114611868576040519150601f19603f3d011682016040523d82523d6000602084013e61186d565b606091505b506000815114156118b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118aa9061239a565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050611910565b600190505b949350505050565b60606000600161192784611a13565b01905060008167ffffffffffffffff81111561194657611945612796565b5b6040519080825280601f01601f1916602001820160405280156119785781602001600182028036833780820191505090505b509050600082602001820190505b6001156119e5578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85816119cf576119ce612738565b5b04945060008514156119e0576119e5565b611986565b819350505050919050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611a71577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381611a6757611a66612738565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310611aae576d04ee2d6d415b85acef81000000008381611aa457611aa3612738565b5b0492506020810190505b662386f26fc100008310611add57662386f26fc100008381611ad357611ad2612738565b5b0492506010810190505b6305f5e1008310611b06576305f5e1008381611afc57611afb612738565b5b0492506008810190505b6127108310611b2b576127108381611b2157611b20612738565b5b0492506004810190505b60648310611b4e5760648381611b4457611b43612738565b5b0492506002810190505b600a8310611b5d576001810190505b80915050919050565b828054611b72906126d5565b90600052602060002090601f016020900481019282611b945760008555611bdb565b82601f10611bad57805160ff1916838001178555611bdb565b82800160010185558215611bdb579182015b82811115611bda578251825591602001919060010190611bbf565b5b509050611be89190611bec565b5090565b5b80821115611c05576000816000905550600101611bed565b5090565b6000611c1c611c178461257a565b612555565b905082815260208101848484011115611c3857611c376127ca565b5b611c43848285612693565b509392505050565b6000611c5e611c59846125ab565b612555565b905082815260208101848484011115611c7a57611c796127ca565b5b611c85848285612693565b509392505050565b600081359050611c9c81612b7e565b92915050565b600081359050611cb181612b95565b92915050565b600081359050611cc681612bac565b92915050565b600081519050611cdb81612bac565b92915050565b600082601f830112611cf657611cf56127c5565b5b8135611d06848260208601611c09565b91505092915050565b600082601f830112611d2457611d236127c5565b5b8135611d34848260208601611c4b565b91505092915050565b600081359050611d4c81612bc3565b92915050565b600060208284031215611d6857611d676127d4565b5b6000611d7684828501611c8d565b91505092915050565b60008060408385031215611d9657611d956127d4565b5b6000611da485828601611c8d565b9250506020611db585828601611c8d565b9150509250929050565b600080600060608486031215611dd857611dd76127d4565b5b6000611de686828701611c8d565b9350506020611df786828701611c8d565b9250506040611e0886828701611d3d565b9150509250925092565b60008060008060808587031215611e2c57611e2b6127d4565b5b6000611e3a87828801611c8d565b9450506020611e4b87828801611c8d565b9350506040611e5c87828801611d3d565b925050606085013567ffffffffffffffff811115611e7d57611e7c6127cf565b5b611e8987828801611ce1565b91505092959194509250565b60008060408385031215611eac57611eab6127d4565b5b6000611eba85828601611c8d565b9250506020611ecb85828601611ca2565b9150509250929050565b60008060408385031215611eec57611eeb6127d4565b5b6000611efa85828601611c8d565b925050602083013567ffffffffffffffff811115611f1b57611f1a6127cf565b5b611f2785828601611d0f565b9150509250929050565b60008060408385031215611f4857611f476127d4565b5b6000611f5685828601611c8d565b9250506020611f6785828601611d3d565b9150509250929050565b600060208284031215611f8757611f866127d4565b5b6000611f9584828501611cb7565b91505092915050565b600060208284031215611fb457611fb36127d4565b5b6000611fc284828501611ccc565b91505092915050565b600060208284031215611fe157611fe06127d4565b5b6000611fef84828501611d3d565b91505092915050565b6120018161261f565b82525050565b61201081612631565b82525050565b6000612021826125dc565b61202b81856125f2565b935061203b8185602086016126a2565b612044816127d9565b840191505092915050565b600061205a826125e7565b6120648185612603565b93506120748185602086016126a2565b61207d816127d9565b840191505092915050565b6000612093826125e7565b61209d8185612614565b93506120ad8185602086016126a2565b80840191505092915050565b60006120c6602d83612603565b91506120d1826127ea565b604082019050919050565b60006120e9603283612603565b91506120f482612839565b604082019050919050565b600061210c602683612603565b915061211782612888565b604082019050919050565b600061212f602583612603565b915061213a826128d7565b604082019050919050565b6000612152601c83612603565b915061215d82612926565b602082019050919050565b6000612175602483612603565b91506121808261294f565b604082019050919050565b6000612198601983612603565b91506121a38261299e565b602082019050919050565b60006121bb602983612603565b91506121c6826129c7565b604082019050919050565b60006121de602e83612603565b91506121e982612a16565b604082019050919050565b6000612201602083612603565b915061220c82612a65565b602082019050919050565b6000612224602083612603565b915061222f82612a8e565b602082019050919050565b6000612247601883612603565b915061225282612ab7565b602082019050919050565b600061226a602183612603565b915061227582612ae0565b604082019050919050565b600061228d603d83612603565b915061229882612b2f565b604082019050919050565b6122ac81612689565b82525050565b60006122be8285612088565b91506122ca8284612088565b91508190509392505050565b60006020820190506122eb6000830184611ff8565b92915050565b60006080820190506123066000830187611ff8565b6123136020830186611ff8565b61232060408301856122a3565b81810360608301526123328184612016565b905095945050505050565b60006020820190506123526000830184612007565b92915050565b60006020820190508181036000830152612372818461204f565b905092915050565b60006020820190508181036000830152612393816120b9565b9050919050565b600060208201905081810360008301526123b3816120dc565b9050919050565b600060208201905081810360008301526123d3816120ff565b9050919050565b600060208201905081810360008301526123f381612122565b9050919050565b6000602082019050818103600083015261241381612145565b9050919050565b6000602082019050818103600083015261243381612168565b9050919050565b600060208201905081810360008301526124538161218b565b9050919050565b60006020820190508181036000830152612473816121ae565b9050919050565b60006020820190508181036000830152612493816121d1565b9050919050565b600060208201905081810360008301526124b3816121f4565b9050919050565b600060208201905081810360008301526124d381612217565b9050919050565b600060208201905081810360008301526124f38161223a565b9050919050565b600060208201905081810360008301526125138161225d565b9050919050565b6000602082019050818103600083015261253381612280565b9050919050565b600060208201905061254f60008301846122a3565b92915050565b600061255f612570565b905061256b8282612707565b919050565b6000604051905090565b600067ffffffffffffffff82111561259557612594612796565b5b61259e826127d9565b9050602081019050919050565b600067ffffffffffffffff8211156125c6576125c5612796565b5b6125cf826127d9565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061262a82612669565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156126c05780820151818401526020810190506126a5565b838111156126cf576000848401525b50505050565b600060028204905060018216806126ed57607f821691505b6020821081141561270157612700612767565b5b50919050565b612710826127d9565b810181811067ffffffffffffffff8211171561272f5761272e612796565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b7f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60008201527f6578697374656e7420746f6b656e000000000000000000000000000000000000602082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b612b878161261f565b8114612b9257600080fd5b50565b612b9e81612631565b8114612ba957600080fd5b50565b612bb58161263d565b8114612bc057600080fd5b50565b612bcc81612689565b8114612bd757600080fd5b5056fea2646970667358221220ef6a821d455871be62a3f43d8255d5a4d5c38b32cf386219756cbc2a800d376864736f6c63430008070033", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "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": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "string", + "name": "tokenURI", + "type": "string" + } + ], + "name": "mintNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "1", + "balance": "99999881872000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x3e5fec24aa4dc4e5aee2e025e51e1392c72a2500577559fae9665c6d52bd6a31": "0x7572690000000000000000000000000000000000000000000000000000000006", + "0xd7c9590abf8c97a7db41f8f2fa12fae115b69950a8904317b51ca0576697a942": "0x01", + "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x4d794e465400000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x4e46540000000000000000000000000000000000000000000000000000000006" + }, + "isSmartContract": true, + "hashBytecode": "0x0634513499d330b238121824f3923dec74b422f1e9a449e078576c351c1d98b6", + "bytecodeLength": 11280 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_0.json b/test/vectors/src/state-transition/forced-tx/test-deploy_0.json new file mode 100644 index 0000000000..84656f43cc --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_0.json @@ -0,0 +1,53 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x97aaef1f70fbd11401986e455cd7352362f404dab8b5534899223b895e87748d", + "batchL2Data": "0xf902c180843b9aca00839896808080b902ad60806040526001600055600260015534801561001a57600080fd5b506102838061002a6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80630f0db778146100675780635ef3d3dd146100835780638ca3165d1461009f578063b698c129146100bd578063e4081625146100d9578063e795befc146100f7575b600080fd5b610081600480360381019061007c91906101bd565b610127565b005b61009d60048036038101906100989190610190565b610143565b005b6100a761014d565b6040516100b4919061020c565b60405180910390f35b6100d760048036038101906100d29190610190565b610153565b005b6100e161015d565b6040516100ee919061020c565b60405180910390f35b610111600480360381019061010c9190610190565b610163565b60405161011e919061020c565b60405180910390f35b8060026000848152602001908152602001600020819055505050565b8060008190555050565b60005481565b8060018190555050565b60015481565b60026020528060005260406000206000915090505481565b60008135905061018a81610236565b92915050565b6000602082840312156101a6576101a5610231565b5b60006101b48482850161017b565b91505092915050565b600080604083850312156101d4576101d3610231565b5b60006101e28582860161017b565b92505060206101f38582860161017b565b9150509250929050565b61020681610227565b82525050565b600060208201905061022160008301846101fd565b92915050565b6000819050919050565b600080fd5b61023f81610227565b811461024a57600080fd5b5056fea26469706673582212205feec680dbd3ffdb3d28421e0c45d9127cc1de581ab1d493e719a7579f16c06964736f6c634300080700338203e9808019eefdfbd3db881a3cc3a80a59188c398ac0b476770e87fcb65bb4d987cfd22a0e3f249df4c944e88c42b4f71a404d659a65ee2b4dbbb6ad689a496dc369f0871b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999763639000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02" + }, + "isSmartContract": true, + "hashBytecode": "0x37b6873a51b6e346373661b3579866c2a9e055364b6734e8232c61a1f2358428", + "bytecodeLength": 643 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_1.json b/test/vectors/src/state-transition/forced-tx/test-deploy_1.json new file mode 100644 index 0000000000..1a16bb34ce --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_1.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0xc0de36c88e976bac1fee0b50f3d99e734cfbe0ecf46334393aab79e9883e2c42", + "batchL2Data": "0xf8ed80843b9aca00839896808080b8da608060405234801561001057600080fd5b5060bb8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063f6d97e8c14602d575b600080fd5b60336047565b604051603e91906062565b60405180910390f35b600080600390508091505090565b605c81607b565b82525050565b6000602082019050607560008301846055565b92915050565b600081905091905056fea2646970667358221220a33fdecaf587db45fa0e1fe4bfca25de09e35bb9a45fa6dab1bf1964244a929164736f6c634300080700338203e98080cac0ac8d23137cd7a8340af28347609ad2a50a0835a9329688bb507243d8738d294b5e44dd33f6b0696134685f71299785188a9b29ed3e1ab4e34dfec429c3641c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999906193000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": {}, + "isSmartContract": true, + "hashBytecode": "0xc0fd06b9925aa0ad80b36b53e4db33fd659858f947ae35572f980fb41f5af5e3", + "bytecodeLength": 187 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_2.json b/test/vectors/src/state-transition/forced-tx/test-deploy_2.json new file mode 100644 index 0000000000..332e5c9194 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_2.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x0cfd97bb06085d283693ed0717b603356e680510135d2f96fab7fd72a2de651d", + "batchL2Data": "0xf8f080843b9aca00839896808080b8dd608060405234801561001057600080fd5b5060be8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063f6d97e8c14602d575b600080fd5b60336047565b604051603e91906065565b60405180910390f35b600060026001018060005260206000f35b605f81607e565b82525050565b6000602082019050607860008301846058565b92915050565b600081905091905056fea2646970667358221220567336b69dcc08145e9e1d6dd7ac560d8e2817fab2aaf6a44043e66a35917c4164736f6c634300080700338203e98080b3c0526e9b3d5afa3c26836fae73feb92977e0c3e35798026cc2698da23daefd6271a22cbb51695060eff7f04e551bf74fd301dba5270ec2ca5673333ce307601b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999905569000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": {}, + "isSmartContract": true, + "hashBytecode": "0x5037b161cfa1abf622d43de10a680f4dec05ea62fb4be3a84c14cbc21ac12ef9", + "bytecodeLength": 190 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_3.json b/test/vectors/src/state-transition/forced-tx/test-deploy_3.json new file mode 100644 index 0000000000..bd7a4ed51f --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_3.json @@ -0,0 +1,167 @@ +{ + "expectedOldStateRoot": "0x8753a67a8c1e1f34361688bcb4ade9a303748a50f396e9b2184224f96f17e688", + "expectedNewStateRoot": "0xadf643098410808ea2bea9afac7a32fce21167adf455084fec31bdf8c5257f71", + "batchL2Data": "0xf901d080843b9aca00839896808080b901bc60806040526001600055600260015534801561001a57600080fd5b5060405161019c38038061019c833981810160405281019061003c919061005e565b80600081905550506100b1565b6000815190506100588161009a565b92915050565b60006020828403121561007457610073610095565b5b600061008284828501610049565b91505092915050565b6000819050919050565b600080fd5b6100a38161008b565b81146100ae57600080fd5b50565b60dd806100bf6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638ca3165d146037578063e4081625146051575b600080fd5b603d606b565b604051604891906084565b60405180910390f35b60576071565b604051606291906084565b60405180910390f35b60005481565b60015481565b607e81609d565b82525050565b6000602082019050609760008301846077565b92915050565b600081905091905056fea26469706673582212207c5d3e8487560f785926787101edb5f7d44e80e7797b1324d73c8a53e83b613764736f6c6343000807003300000000000000000000000000000000000000000000000000000000000000038203e98080c1d85da30f0d87da063621306f1661b93658d60a262a4420ab1a403643160ebc22ae1a96934c29192e1f3092b39f2684b2b238f865c9bfc68e5f6627184e999c1c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c80630f0db778146100675780635ef3d3dd146100835780638ca3165d1461009f578063b698c129146100bd578063e4081625146100d9578063e795befc146100f7575b600080fd5b610081600480360381019061007c91906101bd565b610127565b005b61009d60048036038101906100989190610190565b610143565b005b6100a761014d565b6040516100b4919061020c565b60405180910390f35b6100d760048036038101906100d29190610190565b610153565b005b6100e161015d565b6040516100ee919061020c565b60405180910390f35b610111600480360381019061010c9190610190565b610163565b60405161011e919061020c565b60405180910390f35b8060026000848152602001908152602001600020819055505050565b8060008190555050565b60005481565b8060018190555050565b60015481565b60026020528060005260406000206000915090505481565b60008135905061018a81610236565b92915050565b6000602082840312156101a6576101a5610231565b5b60006101b48482850161017b565b91505092915050565b600080604083850312156101d4576101d3610231565b5b60006101e28582860161017b565b92505060206101f38582860161017b565b9150509250929050565b61020681610227565b82525050565b600060208201905061022160008301846101fd565b92915050565b6000819050919050565b600080fd5b61023f81610227565b811461024a57600080fd5b5056fea26469706673582212205feec680dbd3ffdb3d28421e0c45d9127cc1de581ab1d493e719a7579f16c06964736f6c63430008070033", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stoFirst", + "type": "uint256" + } + ], + "name": "setFirst", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "key", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setMapping", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_stoSecond", + "type": "uint256" + } + ], + "name": "setSecond", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stoFirst", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "stoMapping", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stoSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ] + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999851762000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02" + }, + "isSmartContract": true, + "hashBytecode": "0x37b6873a51b6e346373661b3579866c2a9e055364b6734e8232c61a1f2358428", + "bytecodeLength": 643 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x03", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02" + }, + "isSmartContract": true, + "hashBytecode": "0xd63f653f8df5322d234d592d3d8ad84a1387b4635975f4ed28b7781eb0993d5c", + "bytecodeLength": 221 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_4.json b/test/vectors/src/state-transition/forced-tx/test-deploy_4.json new file mode 100644 index 0000000000..a3a4206410 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_4.json @@ -0,0 +1,62 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x11a1c647963faae7ccfeda0cb3e131c44ea9c9612112d520b7f43e1fb310b6de", + "batchL2Data": "0xf902b680843b9aca0083989680808203e8b902a06080604052600160005560026001556102838061001d6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80630f0db778146100675780635ef3d3dd146100835780638ca3165d1461009f578063b698c129146100bd578063e4081625146100d9578063e795befc146100f7575b600080fd5b610081600480360381019061007c91906101bd565b610127565b005b61009d60048036038101906100989190610190565b610143565b005b6100a761014d565b6040516100b4919061020c565b60405180910390f35b6100d760048036038101906100d29190610190565b610153565b005b6100e161015d565b6040516100ee919061020c565b60405180910390f35b610111600480360381019061010c9190610190565b610163565b60405161011e919061020c565b60405180910390f35b8060026000848152602001908152602001600020819055505050565b8060008190555050565b60005481565b8060018190555050565b60015481565b60026020528060005260406000206000915090505481565b60008135905061018a81610236565b92915050565b6000602082840312156101a6576101a5610231565b5b60006101b48482850161017b565b91505092915050565b600080604083850312156101d4576101d3610231565b5b60006101e28582860161017b565b92505060206101f38582860161017b565b9150509250929050565b61020681610227565b82525050565b600060208201905061022160008301846101fd565b92915050565b6000819050919050565b600080fd5b61023f81610227565b811461024a57600080fd5b5056fea2646970667358221220d39e086335057db80f702ebac8a7123339d84f5501a81e2fa31d5c84c858fbb564736f6c634300080700338203e980802bb880737b4dfb4bb677e000279b1d014ff1a79c1fce47809f42f52d0f09c371584aac5148581555ab9928c273b928f7d98808d44836aa364df5bdbe9267b2831c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999763846999999000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "0", + "balance": "0", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "1000", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x02" + }, + "isSmartContract": true, + "hashBytecode": "0xb441dc6e3f86a7e79eb2580a11d42c8e4fc8021f0a3d2f9f2383c26204800fb8", + "bytecodeLength": 643 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_5.json b/test/vectors/src/state-transition/forced-tx/test-deploy_5.json new file mode 100644 index 0000000000..cef257086d --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_5.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x8d10f51e5cc698c8336fd16e92914a15535126e5a1f1917c45fc5697b81f6b89", + "batchL2Data": "0xf9025c80843b9aca00839896808080b9024860c060405234801561001057600080fd5b506040516102083803806102088339818101604052810190610032919061005e565b81608081815250508060a0818152505050506100c4565b600081519050610058816100ad565b92915050565b60008060408385031215610075576100746100a8565b5b600061008385828601610049565b925050602061009485828601610049565b9150509250929050565b6000819050919050565b600080fd5b6100b68161009e565b81146100c157600080fd5b50565b60805160a0516101216100e76000396000606f01526000609701526101216000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806395f0dc561460375780639c1c8cd5146051575b600080fd5b603d606b565b6040516048919060c8565b60405180910390f35b60576093565b6040516062919060c8565b60405180910390f35b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60007f0000000000000000000000000000000000000000000000000000000000000000905090565b60c28160e1565b82525050565b600060208201905060db600083018460bb565b92915050565b600081905091905056fea26469706673582212207f356e07508d69b3fa2c37ec79e1ccca75b7a002c4fed3112e8cb881341b6d6664736f6c63430008070033000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000058203e98080f8347fb95f3385725c21f94be1c30ec289a41e6e9d60355e1140686357692d135cb58f643b8757c7bae2a9f36e2a4db59ba2a632c10025b0c73060ce18b20a781c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999881156000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": {}, + "isSmartContract": true, + "hashBytecode": "0xd8760e4a0dc3375ecb1191fb3de0799a5b34905f9bb6ab789bdaaa4cca1ced55", + "bytecodeLength": 289 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_6.json b/test/vectors/src/state-transition/forced-tx/test-deploy_6.json new file mode 100644 index 0000000000..20d974c3d1 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_6.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x39010aae529e7caaec6c5e9e82942388a84fc714f5ed89c2b8272be45ecd58e8", + "batchL2Data": "0xf8d480843b9aca00839896808080b8c16080604052348015600f57600080fd5b506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016040906068565b60405180910390fd5b600060546014836086565b9150605d826097565b602082019050919050565b60006020820190508181036000830152607f816049565b9050919050565b600082825260208201905092915050565b7f546f646179206973206e6f74206a7565726e657300000000000000000000000060008201525056fe8203e980803c79ee9a646fda0d557aab8446858e6af7635b94199d8e44f5d451ce043b8cd66e7be5c573b7b48c11819543d5c2dd179e41cb9d8b4dafba491a665389ae090c1c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999944123000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "0", + "balance": "0", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_7.json b/test/vectors/src/state-transition/forced-tx/test-deploy_7.json new file mode 100644 index 0000000000..c108ffefa2 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_7.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x9846547dc5cd96884e99b0b54dceb6a63a66c7dd56ffa0bf81f7f642d8f12858", + "batchL2Data": "0xf902ed80843b9aca00839896808080b902d9608060405234801561001057600080fd5b507f5e7df75d54e493185612379c616118a4c9ac802de621b010c96f74d22df4b30a60405160405180910390a160017f977224b24e70d33f3be87246a29c5636cfc8dd6853e175b54af01ff493ffac6260405160405180910390a2600260017fbb6e4da744abea70325874159d52c1ad3e57babfae7c329a948e7dcb274deb0960405160405180910390a36003600260017f966018f1afaee50c6bcf5eb4ae089eeb650bd1deb473395d69dd307ef2e689b760405160405180910390a46003600260017fe5562b12d9276c5c987df08afff7b1946f2d869236866ea2285c7e2e95685a6460046040516101039190610243565b60405180910390a46002600360047fe5562b12d9276c5c987df08afff7b1946f2d869236866ea2285c7e2e95685a6460016040516101419190610228565b60405180910390a46001600260037f966018f1afaee50c6bcf5eb4ae089eeb650bd1deb473395d69dd307ef2e689b760405160405180910390a4600160027fbb6e4da744abea70325874159d52c1ad3e57babfae7c329a948e7dcb274deb0960405160405180910390a360017f977224b24e70d33f3be87246a29c5636cfc8dd6853e175b54af01ff493ffac6260405160405180910390a27f5e7df75d54e493185612379c616118a4c9ac802de621b010c96f74d22df4b30a60405160405180910390a161028c565b61021381610268565b82525050565b6102228161027a565b82525050565b600060208201905061023d600083018461020a565b92915050565b60006020820190506102586000830184610219565b92915050565b6000819050919050565b60006102738261025e565b9050919050565b60006102858261025e565b9050919050565b603f8061029a6000396000f3fe6080604052600080fdfea2646970667358221220c89c147a8f1ba311a26177439cf337807bf64de37bc21b71f665b3043b7d2c4364736f6c634300080700338203e980805f5746ff556f87c10a8abb44e7a13db663f417f37280d6bc2e99c3f9ab2527281986ef7b294c9de80999cdd4a3050bf7a104e18ba907bfa547b4f6510e08b8371c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999907344000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": {}, + "isSmartContract": true, + "hashBytecode": "0xc4ca8a86a1c7c064e09634baa786b310ed20928afe2ef4aeb86b6531e46a6ceb", + "bytecodeLength": 63 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_8.json b/test/vectors/src/state-transition/forced-tx/test-deploy_8.json new file mode 100644 index 0000000000..53df5177b3 --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_8.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x4aa19c51eb07bc73d52f8e9e7103ca303816b2c3827947947a53da75a4ccfba6", + "batchL2Data": "0xdc80843b9aca008398968080808a60ef60005360026000f38203e980808d264aa1745e34572547dd19a1a6d37dfd3765876904f68dde2d20988d7aa1347ca74e0bf2c1f7d1ca6e84639663cdd809882d6deec84bb0b21a86eb85b3e24c1c", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199990000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "0", + "balance": "0", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/test-deploy_9.json b/test/vectors/src/state-transition/forced-tx/test-deploy_9.json new file mode 100644 index 0000000000..9822faa60c --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/test-deploy_9.json @@ -0,0 +1,50 @@ +{ + "expectedOldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "expectedNewStateRoot": "0x125ca3a42a96ffbebeaf99b49e6ad8dd945940d0a511ae070737ea60446333c0", + "batchL2Data": "0xdc80843b9aca008398968080808a60fe60005360016000f38203e980808661f7b55af56b5a525522dcd162ec2a1352e85fd0df7a3f78702f47e8909d7e426d4682823b4bfb2ece0a92aef0d0649f2da011caaeb39986e18eae1b2ec5ab1b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + } + ], + "expectedNewLeafs": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "1", + "balance": "199999946646000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0xA72217948Ea7D968A64c77F83908cea136bBF964", + "nonce": "1", + "balance": "0", + "storage": {}, + "isSmartContract": true, + "hashBytecode": "0xd15878a5ba149d561dbcb74a385388fa6b1f77a1b75af2d95136f8c747edb9c3", + "bytecodeLength": 1 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/state-transition/forced-tx/uniswapv2_1.json b/test/vectors/src/state-transition/forced-tx/uniswapv2_1.json new file mode 100644 index 0000000000..53dba3e24f --- /dev/null +++ b/test/vectors/src/state-transition/forced-tx/uniswapv2_1.json @@ -0,0 +1,1151 @@ +{ + "expectedOldStateRoot": "0x663c9716c7e0481e0edbc33a2c09045e3e47c82fc030cebd676b687217c1f322", + "expectedNewStateRoot": "0x46c7b989e545570909cef3723ad845012bff3d452e3d72d0047bd2cf729f9c9d", + "batchL2Data": "0xf86b80843b9aca00830186a09413db4b51c5174ee2366e878a367aa1d426970ade80b84440c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff0000000000000000000000000000000000000000000000008ac7230489e800008203e9808093b92302f6fe4ef2504a8fc808e0cd88007f63af52b894a6235c8dae7e4be21674a8494b41eed4ee4a57dea8a52e28c459b24c889eb5219688f3830f6305f2e71bf86b01843b9aca00830186a09485e844b762a271022b692cf99ce5c59ba0650ac880b84440c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff0000000000000000000000000000000000000000000000008ac7230489e800008203e98080de9ff31e99a3d1f2e766520f78742316945c6b411fe6ba3fa5315fd2ad81dbf1184327140e0a59a09583806f1f226ea6282035631f17914aa5fd6fbd2e06f71e1cf86b02843b9aca00830186a09413db4b51c5174ee2366e878a367aa1d426970ade80b84440c10f19000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d00000000000000000000000000000000000000000000000246ddf979766800008203e98080e6440fe6452f3f960fa0452adbcd4096c47e64170b489c582ad24b7263f8173e0f5ae79c17954593a48f6217581bc69597872f4f5bcbeab083094779daa820b91cf86b80843b9aca0083989680941275fbb540c8efc58b812ba83b0d0b8b9917ae9880b844c9c6539600000000000000000000000085e844b762a271022b692cf99ce5c59ba0650ac800000000000000000000000013db4b51c5174ee2366e878a367aa1d426970ade8203e9808033a952f7c311d38e2ea7e60466bfd185dd2dd21c13f38e212e938a085b4bde3954d89219d3413384d44818a825e82e089f88b89d209ac7b7c896f24c8b9948cd1bf86b01843b9aca00830186a09413db4b51c5174ee2366e878a367aa1d426970ade80b844a9059cbb000000000000000000000000d40ab51c8141fab2fe0f42c687d7bc73a950221200000000000000000000000000000000000000000000000029a2241af62c00008203e98080b4ec2da217275d82767e9c99fd3d450928f2ecc803f496acdbe7c0f6dcbe11750a24332286f8f1162dfb74a7c121f80d454efedb32ad2b3eb2a78dd4b65db8511bf86b02843b9aca00830186a09485e844b762a271022b692cf99ce5c59ba0650ac880b844a9059cbb000000000000000000000000d40ab51c8141fab2fe0f42c687d7bc73a950221200000000000000000000000000000000000000000000000029a2241af62c00008203e98080352d33079bc7dce2a9315126b60c5615a1592548bd7a8001f24df6aa2e220a766c8b7678e5ce30ca086cf8a416a8e15ffe3f7e480aa75c3f72a7fa347634453f1bf84a03843b9aca00830f424094d40ab51c8141fab2fe0f42c687d7bc73a950221280a46a6278420000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff8203e98080ce3d4396a74f501d7aa32c07fa1e27a2284fa923474a7be795bd1e3df780423043fdae4f5420656b5265c6afb1e79313e37b22f506d57b69dda668ceb64dbd471cf86b03843b9aca00830186a09413db4b51c5174ee2366e878a367aa1d426970ade80b844a9059cbb000000000000000000000000d40ab51c8141fab2fe0f42c687d7bc73a95022120000000000000000000000000000000000000000000000000de0b6b3a76400008203e9808090bac11033e174995789447f9142fb0fec61f443c38248ce1ea3438433bd194d5bdc508d3374cd70310d6c151dd64a1b0efeca2f3e03e0747a8bf8acf23886a91cf8cb04843b9aca008398968094d40ab51c8141fab2fe0f42c687d7bc73a950221280b8a4022c0d9f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4502144dca0000000000000000000000000000617b3a3528f9cdd6630fd3301b9c8911f7bf063d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000008203e98080edaa1823fc82caa3f28fef51761cf69189b74174d910627aebbb8e434b04f1f847ef99a420816335637042e0adbc3cc65a0030d96bccdd7527d20a44ba6bd3101b", + "genesis": [ + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "0", + "balance": "100000000000000000000", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "isSmartContract": false + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "0", + "balance": "200000000000000000000", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", + "isSmartContract": false + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a2e74af61161005b578063a2e74af6146101ad578063c9c65396146101f1578063e6a4390514610295578063f46901ed1461033957610088565b8063017e7e581461008d578063094b7415146100d75780631e3dd18b14610121578063574f2ba31461018f575b600080fd5b61009561037d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100df6103a2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61014d6004803603602081101561013757600080fd5b81019080803590602001909291905050506103c8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610197610404565b6040518082815260200191505060405180910390f35b6101ef600480360360208110156101c357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610411565b005b6102536004803603604081101561020757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610518565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102f7600480360360408110156102ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bf5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61037b6004803603602081101561034f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c37565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600381815481106103d557fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600380549050905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f556e697377617056323a20464f5242494444454e00000000000000000000000081525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f556e697377617056323a204944454e544943414c5f414444524553534553000081525060200191505060405180910390fd5b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16106105f95783856105fc565b84845b91509150600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156106a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f556e697377617056323a205a45524f5f4144445245535300000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f556e697377617056323a20504149525f4558495354530000000000000000000081525060200191505060405180910390fd5b6060604051806020016107f390610d3d565b6020820181038252601f19601f82011660405250905060008383604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050808251602084016000f594508473ffffffffffffffffffffffffffffffffffffffff1663485cc95585856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050600060405180830381600087803b15801561095957600080fd5b505af115801561096d573d6000803e3d6000fd5b5050505084600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555084600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e987600380549050604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a35050505092915050565b60026020528160005260406000206020528060005260406000206000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610cfa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f556e697377617056323a20464f5242494444454e00000000000000000000000081525060200191505060405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b613c3180610d4b8339019056fe60806040526001600c5534801561001557600080fd5b5060004690506040518080613bdf60529139605201905060405180910390206040518060400160405280600a81526020017f556e697377617020563200000000000000000000000000000000000000000000815250805190602001206040518060400160405280600181526020017f3100000000000000000000000000000000000000000000000000000000000000815250805190602001208330604051602001808681526020018581526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200195505050505050604051602081830303815290604052805190602001206003819055505033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613a6a806101756000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a7146108c4578063d505accf1461090e578063dd62ed3e146109a7578063fff6cae914610a1f576101a9565b8063ba9a7a5614610818578063bc25cf7714610836578063c45a01551461087a576101a9565b80637ecebe00116100d35780637ecebe001461067857806389afcb44146106d057806395d89b411461072f578063a9059cbb146107b2576101a9565b80636a627842146105aa57806370a08231146106025780637464fc3d1461065a576101a9565b806323b872dd116101665780633644e515116101405780633644e515146104ec578063485cc9551461050a5780635909c0d51461056e5780635a3d54931461058c576101a9565b806323b872dd1461042457806330adf81f146104aa578063313ce567146104c8576101a9565b8063022c0d9f146101ae57806306fdde031461025b5780630902f1ac146102de578063095ea7b3146103565780630dfe1681146103bc57806318160ddd14610406575b600080fd5b610259600480360360808110156101c457600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561021557600080fd5b82018360208201111561022757600080fd5b8035906020019184600183028401116401000000008311171561024957600080fd5b9091929391929390505050610a29565b005b610263611216565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102a3578082015181840152602081019050610288565b50505050905090810190601f1680156102d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102e661124f565b60405180846dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168152602001836dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390f35b6103a26004803603604081101561036c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112ac565b604051808215151515815260200191505060405180910390f35b6103c46112c3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61040e6112e9565b6040518082815260200191505060405180910390f35b6104906004803603606081101561043a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112ef565b604051808215151515815260200191505060405180910390f35b6104b26114ba565b6040518082815260200191505060405180910390f35b6104d06114e1565b604051808260ff1660ff16815260200191505060405180910390f35b6104f46114e6565b6040518082815260200191505060405180910390f35b61056c6004803603604081101561052057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114ec565b005b610576611635565b6040518082815260200191505060405180910390f35b61059461163b565b6040518082815260200191505060405180910390f35b6105ec600480360360208110156105c057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611641565b6040518082815260200191505060405180910390f35b6106446004803603602081101561061857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611af2565b6040518082815260200191505060405180910390f35b610662611b0a565b6040518082815260200191505060405180910390f35b6106ba6004803603602081101561068e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b10565b6040518082815260200191505060405180910390f35b610712600480360360208110156106e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b28565b604051808381526020018281526020019250505060405180910390f35b610737612115565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561077757808201518184015260208101905061075c565b50505050905090810190601f1680156107a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6107fe600480360360408110156107c857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061214e565b604051808215151515815260200191505060405180910390f35b610820612165565b6040518082815260200191505060405180910390f35b6108786004803603602081101561084c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061216b565b005b610882612446565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108cc61246c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109a5600480360360e081101561092457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612492565b005b610a09600480360360408110156109bd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506127d6565b6040518082815260200191505060405180910390f35b610a276127fb565b005b6001600c5414610aa1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000851180610ab85750600084115b610b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061397c6025913960400191505060405180910390fd5b600080610b1861124f565b5091509150816dffffffffffffffffffffffffffff1687108015610b4b5750806dffffffffffffffffffffffffffff1686105b610ba0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806139c56021913960400191505060405180910390fd5b6000806000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614158015610c5957508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b610ccb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e697377617056323a20494e56414c49445f544f000000000000000000000081525060200191505060405180910390fd5b60008b1115610ce057610cdf828a8d612a7b565b5b60008a1115610cf557610cf4818a8c612a7b565b5b6000888890501115610ddd578873ffffffffffffffffffffffffffffffffffffffff166310d1e85c338d8d8c8c6040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b158015610dc457600080fd5b505af1158015610dd8573d6000803e3d6000fd5b505050505b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610e5a57600080fd5b505afa158015610e6e573d6000803e3d6000fd5b505050506040513d6020811015610e8457600080fd5b810190808051906020019092919050505093508073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610f1457600080fd5b505afa158015610f28573d6000803e3d6000fd5b505050506040513d6020811015610f3e57600080fd5b810190808051906020019092919050505092505050600089856dffffffffffffffffffffffffffff16038311610f75576000610f8b565b89856dffffffffffffffffffffffffffff160383035b9050600089856dffffffffffffffffffffffffffff16038311610faf576000610fc5565b89856dffffffffffffffffffffffffffff160383035b90506000821180610fd65750600081115b61102b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139a16024913960400191505060405180910390fd5b6000611067611044600385612cc890919063ffffffff16565b6110596103e888612cc890919063ffffffff16565b612d5d90919063ffffffff16565b905060006110a5611082600385612cc890919063ffffffff16565b6110976103e888612cc890919063ffffffff16565b612d5d90919063ffffffff16565b90506110ef620f42406110e1896dffffffffffffffffffffffffffff168b6dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b612cc890919063ffffffff16565b6111028284612cc890919063ffffffff16565b1015611176576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f556e697377617056323a204b000000000000000000000000000000000000000081525060200191505060405180910390fd5b505061118484848888612de0565b8873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d82284848f8f6040518085815260200184815260200183815260200182815260200194505050505060405180910390a35050505050506001600c819055505050505050565b6040518060400160405280600a81526020017f556e69737761702056320000000000000000000000000000000000000000000081525081565b6000806000600860009054906101000a90046dffffffffffffffffffffffffffff1692506008600e9054906101000a90046dffffffffffffffffffffffffffff1691506008601c9054906101000a900463ffffffff169050909192565b60006112b933848461315e565b6001905092915050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146114a45761142382600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6114af848484613249565b600190509392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960001b81565b601281565b60035481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f556e697377617056323a20464f5242494444454e00000000000000000000000081525060200191505060405180910390fd5b81600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60095481565b600a5481565b60006001600c54146116bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000806116ce61124f565b50915091506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561177457600080fd5b505afa158015611788573d6000803e3d6000fd5b505050506040513d602081101561179e57600080fd5b810190808051906020019092919050505090506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561185257600080fd5b505afa158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b8101908080519060200190929190505050905060006118b4856dffffffffffffffffffffffffffff1684612d5d90919063ffffffff16565b905060006118db856dffffffffffffffffffffffffffff1684612d5d90919063ffffffff16565b905060006118e987876133dd565b9050600080549050600081141561193d576119296103e861191b6119168688612cc890919063ffffffff16565b6135be565b612d5d90919063ffffffff16565b985061193860006103e8613620565b6119a0565b61199d886dffffffffffffffffffffffffffff166119648387612cc890919063ffffffff16565b8161196b57fe5b04886dffffffffffffffffffffffffffff166119908487612cc890919063ffffffff16565b8161199757fe5b0461373a565b98505b600089116119f9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180613a0e6028913960400191505060405180910390fd5b611a038a8a613620565b611a0f86868a8a612de0565b8115611a8757611a806008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b600b819055505b3373ffffffffffffffffffffffffffffffffffffffff167f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f8585604051808381526020018281526020019250505060405180910390a250505050505050506001600c81905550919050565b60016020528060005260406000206000915090505481565b600b5481565b60046020528060005260406000206000915090505481565b6000806001600c5414611ba3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c81905550600080611bb661124f565b50915091506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611c8857600080fd5b505afa158015611c9c573d6000803e3d6000fd5b505050506040513d6020811015611cb257600080fd5b8101908080519060200190929190505050905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611d4457600080fd5b505afa158015611d58573d6000803e3d6000fd5b505050506040513d6020811015611d6e57600080fd5b810190808051906020019092919050505090506000600160003073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000611dd188886133dd565b905060008054905080611ded8685612cc890919063ffffffff16565b81611df457fe5b049a5080611e0b8585612cc890919063ffffffff16565b81611e1257fe5b04995060008b118015611e25575060008a115b611e7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806139e66028913960400191505060405180910390fd5b611e843084613753565b611e8f878d8d612a7b565b611e9a868d8c612a7b565b8673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611f1757600080fd5b505afa158015611f2b573d6000803e3d6000fd5b505050506040513d6020811015611f4157600080fd5b810190808051906020019092919050505094508573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611fd157600080fd5b505afa158015611fe5573d6000803e3d6000fd5b505050506040513d6020811015611ffb57600080fd5b8101908080519060200190929190505050935061201a85858b8b612de0565b81156120925761208b6008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b600b819055505b8b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d819364968d8d604051808381526020018281526020019250505060405180910390a35050505050505050506001600c81905550915091565b6040518060400160405280600681526020017f554e492d5632000000000000000000000000000000000000000000000000000081525081565b600061215b338484613249565b6001905092915050565b6103e881565b6001600c54146121e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506123398284612334600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156122eb57600080fd5b505afa1580156122ff573d6000803e3d6000fd5b505050506040513d602081101561231557600080fd5b8101908080519060200190929190505050612d5d90919063ffffffff16565b612a7b565b61243981846124346008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156123eb57600080fd5b505afa1580156123ff573d6000803e3d6000fd5b505050506040513d602081101561241557600080fd5b8101908080519060200190929190505050612d5d90919063ffffffff16565b612a7b565b50506001600c8190555050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b42841015612508576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f556e697377617056323a2045585049524544000000000000000000000000000081525060200191505060405180910390fd5b60006003547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960001b898989600460008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050558a604051602001808781526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012060405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156126da573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561274e57508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6127c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f556e697377617056323a20494e56414c49445f5349474e41545552450000000081525060200191505060405180910390fd5b6127cb89898961315e565b505050505050505050565b6002602052816000526040600020602052806000526040600020600091509150505481565b6001600c5414612873576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c81905550612a71600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561291d57600080fd5b505afa158015612931573d6000803e3d6000fd5b505050506040513d602081101561294757600080fd5b8101908080519060200190929190505050600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d6020811015612a2157600080fd5b8101908080519060200190929190505050600860009054906101000a90046dffffffffffffffffffffffffffff166008600e9054906101000a90046dffffffffffffffffffffffffffff16612de0565b6001600c81905550565b600060608473ffffffffffffffffffffffffffffffffffffffff166040518060400160405280601981526020017f7472616e7366657228616464726573732c75696e743235362900000000000000815250805190602001208585604051602401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310612ba85780518252602082019150602081019050602083039250612b85565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612c0a576040519150601f19603f3d011682016040523d82523d6000602084013e612c0f565b606091505b5091509150818015612c4f5750600081511480612c4e5750808060200190516020811015612c3c57600080fd5b81019080805190602001909291905050505b5b612cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f556e697377617056323a205452414e534645525f4641494c454400000000000081525060200191505060405180910390fd5b5050505050565b600080821480612ce55750828283850292508281612ce257fe5b04145b612d57576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b92915050565b6000828284039150811115612dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f64732d6d6174682d7375622d756e646572666c6f77000000000000000000000081525060200191505060405180910390fd5b92915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff168411158015612e5057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff168311155b612ec2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e697377617056323a204f564552464c4f570000000000000000000000000081525060200191505060405180910390fd5b60006401000000004281612ed257fe5b06905060006008601c9054906101000a900463ffffffff168203905060008163ffffffff16118015612f1557506000846dffffffffffffffffffffffffffff1614155b8015612f3257506000836dffffffffffffffffffffffffffff1614155b15613014578063ffffffff16612f7785612f4b8661386d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661389890919063ffffffff16565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16026009600082825401925050819055508063ffffffff16612fe584612fb98761386d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661389890919063ffffffff16565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1602600a600082825401925050819055505b85600860006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550846008600e6101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550816008601c6101000a81548163ffffffff021916908363ffffffff1602179055507f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1600860009054906101000a90046dffffffffffffffffffffffffffff166008600e9054906101000a90046dffffffffffffffffffffffffffff1660405180836dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168152602001826dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b61329b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061333081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546138f890919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141591506000600b54905082156135a4576000811461359f57600061350a613505866dffffffffffffffffffffffffffff16886dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b6135be565b90506000613517836135be565b90508082111561359c57600061354a6135398385612d5d90919063ffffffff16565b600054612cc890919063ffffffff16565b9050600061357483613566600587612cc890919063ffffffff16565b6138f890919063ffffffff16565b9050600081838161358157fe5b0490506000811115613598576135978782613620565b5b5050505b50505b6135b6565b600081146135b5576000600b819055505b5b505092915050565b6000600382111561360d5781905060006001600284816135da57fe5b040190505b81811015613607578091506002818285816135f657fe5b0401816135ff57fe5b0490506135df565b5061361b565b6000821461361a57600190505b5b919050565b613635816000546138f890919063ffffffff16565b60008190555061368d81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546138f890919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b6000818310613749578161374b565b825b905092915050565b6137a581600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506137fd81600054612d5d90919063ffffffff16565b600081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60006e010000000000000000000000000000826dffffffffffffffffffffffffffff16029050919050565b6000816dffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16816138ef57fe5b04905092915050565b6000828284019150811015613975576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b9291505056fe556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f494e5055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f4c4951554944495459556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4255524e4544556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4d494e544544a265627a7a723158201e03882ebfce3a1b9c942173f1189e5b58092e06efc20e737913bcf2531be1cb64736f6c63430005100032454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429a265627a7a72315820950796810300b696dd393c16523c157d87b5d22f1161eef706af18cc772d6bed64736f6c63430005100032", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "feeToSetter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "name": "setFeeToSetter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + { + "address": "0x85e844b762a271022b692cf99ce5c59ba0650ac8", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5a4b434f494e410000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5a4b434f494e410000000000000000000000000000000000000000000000000e" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806370a08231116100ad57806395d89b411161007157806395d89b41146102fa578063a457c2d714610318578063a9059cbb14610348578063dd62ed3e14610378578063f2fde38b146103a857610121565b806370a082311461027a578063715018a6146102aa5780637d64bcb4146102b45780638da5cb5b146102be5780638f1c56bd146102dc57610121565b806323b872dd116100f457806323b872dd146101b0578063313ce567146101e057806339509351146101fe57806340b8405a1461022e57806340c10f191461025e57610121565b806305d2035b1461012657806306fdde0314610144578063095ea7b31461016257806318160ddd14610192575b600080fd5b61012e6103c4565b60405161013b919061186f565b60405180910390f35b61014c6103db565b604051610159919061188a565b60405180910390f35b61017c60048036038101906101779190611664565b61046d565b604051610189919061186f565b60405180910390f35b61019a61048b565b6040516101a791906119cc565b60405180910390f35b6101ca60048036038101906101c59190611611565b610495565b6040516101d7919061186f565b60405180910390f35b6101e861056e565b6040516101f591906119e7565b60405180910390f35b61021860048036038101906102139190611664565b610585565b604051610225919061186f565b60405180910390f35b610248600480360381019061024391906115a4565b610638565b60405161025591906119cc565b60405180910390f35b61027860048036038101906102739190611664565b6106c5565b005b610294600480360381019061028f91906115a4565b610723565b6040516102a191906119cc565b60405180910390f35b6102b261076b565b005b6102bc6108c3565b005b6102c661091d565b6040516102d39190611854565b60405180910390f35b6102e4610947565b6040516102f191906119cc565b60405180910390f35b61030261094d565b60405161030f919061188a565b60405180910390f35b610332600480360381019061032d9190611664565b6109df565b60405161033f919061186f565b60405180910390f35b610362600480360381019061035d9190611664565b610aac565b60405161036f919061186f565b60405180910390f35b610392600480360381019061038d91906115d1565b610aca565b60405161039f91906119cc565b60405180910390f35b6103c260048036038101906103bd91906115a4565b610b51565b005b6000600760009054906101000a900460ff16905090565b6060600380546103ea90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461041690611b30565b80156104635780601f1061043857610100808354040283529160200191610463565b820191906000526020600020905b81548152906001019060200180831161044657829003601f168201915b5050505050905090565b600061048161047a610d18565b8484610d20565b6001905092915050565b6000600254905090565b60006104a2848484610eeb565b610563846104ae610d18565b61055e85604051806060016040528060288152602001611e8060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610514610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b600190509392505050565b6000600560009054906101000a900460ff16905090565b600061062e610592610d18565b8461062985600160006105a3610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b610d20565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546006819055506000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600760009054906101000a900460ff1615610715576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161070c9061198c565b60405180910390fd5b61071f8282611242565b5050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610773610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f99061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600760009054906101000a900460ff1615610913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090a9061198c565b60405180910390fd5b61091b6112e7565b565b6000600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60606004805461095c90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461098890611b30565b80156109d55780601f106109aa576101008083540402835291602001916109d5565b820191906000526020600020905b8154815290600101906020018083116109b857829003601f168201915b5050505050905090565b6000610aa26109ec610d18565b84610a9d85604051806060016040528060258152602001611ea86025913960016000610a16610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b6001905092915050565b6000610ac0610ab9610d18565b8484610eeb565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610b59610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610be8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdf9061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610c58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4f906118cc565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610d90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d879061196c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df7906118ec565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610ede91906119cc565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061194c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc2906118ac565b60405180910390fd5b610fd6838383611388565b61104181604051806060016040528060268152602001611e5a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110d4816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161117391906119cc565b60405180910390a3505050565b60008383111582906111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf919061188a565b60405180910390fd5b50600083856111d79190611a74565b9050809150509392505050565b60008082846111f39190611a1e565b905083811015611238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122f9061190c565b60405180910390fd5b8091505092915050565b61124a610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d09061192c565b60405180910390fd5b6112e38282611398565b5050565b6112ef610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461137e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113759061192c565b60405180910390fd5b61138661152c565b565b611393838383611575565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611408576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ff906119ac565b60405180910390fd5b61141460008383611388565b611429816002546111e490919063ffffffff16565b600281905550611480816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161152091906119cc565b60405180910390a35050565b6001600760006101000a81548160ff0219169083151502179055507fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0860405160405180910390a1565b505050565b60008135905061158981611e2b565b92915050565b60008135905061159e81611e42565b92915050565b6000602082840312156115ba576115b9611bc0565b5b60006115c88482850161157a565b91505092915050565b600080604083850312156115e8576115e7611bc0565b5b60006115f68582860161157a565b92505060206116078582860161157a565b9150509250929050565b60008060006060848603121561162a57611629611bc0565b5b60006116388682870161157a565b93505060206116498682870161157a565b925050604061165a8682870161158f565b9150509250925092565b6000806040838503121561167b5761167a611bc0565b5b60006116898582860161157a565b925050602061169a8582860161158f565b9150509250929050565b6116ad81611aa8565b82525050565b6116bc81611aba565b82525050565b60006116cd82611a02565b6116d78185611a0d565b93506116e7818560208601611afd565b6116f081611bc5565b840191505092915050565b6000611708602383611a0d565b915061171382611bd6565b604082019050919050565b600061172b602683611a0d565b915061173682611c25565b604082019050919050565b600061174e602283611a0d565b915061175982611c74565b604082019050919050565b6000611771601b83611a0d565b915061177c82611cc3565b602082019050919050565b6000611794602083611a0d565b915061179f82611cec565b602082019050919050565b60006117b7602583611a0d565b91506117c282611d15565b604082019050919050565b60006117da602483611a0d565b91506117e582611d64565b604082019050919050565b60006117fd602283611a0d565b915061180882611db3565b604082019050919050565b6000611820601f83611a0d565b915061182b82611e02565b602082019050919050565b61183f81611ae6565b82525050565b61184e81611af0565b82525050565b600060208201905061186960008301846116a4565b92915050565b600060208201905061188460008301846116b3565b92915050565b600060208201905081810360008301526118a481846116c2565b905092915050565b600060208201905081810360008301526118c5816116fb565b9050919050565b600060208201905081810360008301526118e58161171e565b9050919050565b6000602082019050818103600083015261190581611741565b9050919050565b6000602082019050818103600083015261192581611764565b9050919050565b6000602082019050818103600083015261194581611787565b9050919050565b60006020820190508181036000830152611965816117aa565b9050919050565b60006020820190508181036000830152611985816117cd565b9050919050565b600060208201905081810360008301526119a5816117f0565b9050919050565b600060208201905081810360008301526119c581611813565b9050919050565b60006020820190506119e16000830184611836565b92915050565b60006020820190506119fc6000830184611845565b92915050565b600081519050919050565b600082825260208201905092915050565b6000611a2982611ae6565b9150611a3483611ae6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115611a6957611a68611b62565b5b828201905092915050565b6000611a7f82611ae6565b9150611a8a83611ae6565b925082821015611a9d57611a9c611b62565b5b828203905092915050565b6000611ab382611ac6565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015611b1b578082015181840152602081019050611b00565b83811115611b2a576000848401525b50505050565b60006002820490506001821680611b4857607f821691505b60208210811415611b5c57611b5b611b91565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600080fd5b6000601f19601f8301169050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f45524332304d696e7461626c653a206d696e74696e672069732066696e69736860008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b611e3481611aa8565b8114611e3f57600080fd5b50565b611e4b81611ae6565b8114611e5657600080fd5b5056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122011d6aa32a52f13724439331c99d3ab1777561b1fe5e60286e4c692fe36f90b1064736f6c63430008070033", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event" + }, + { + "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": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finishMinting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "updateBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + { + "address": "0x13db4b51c5174ee2366e878a367aa1d426970ade", + "nonce": "1", + "balance": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5a4b434f494e420000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5a4b434f494e420000000000000000000000000000000000000000000000000e" + }, + "isSmartContract": true, + "bytecode": "0x608060405234801561001057600080fd5b50600436106101215760003560e01c806370a08231116100ad57806395d89b411161007157806395d89b41146102fa578063a457c2d714610318578063a9059cbb14610348578063dd62ed3e14610378578063f2fde38b146103a857610121565b806370a082311461027a578063715018a6146102aa5780637d64bcb4146102b45780638da5cb5b146102be5780638f1c56bd146102dc57610121565b806323b872dd116100f457806323b872dd146101b0578063313ce567146101e057806339509351146101fe57806340b8405a1461022e57806340c10f191461025e57610121565b806305d2035b1461012657806306fdde0314610144578063095ea7b31461016257806318160ddd14610192575b600080fd5b61012e6103c4565b60405161013b919061186f565b60405180910390f35b61014c6103db565b604051610159919061188a565b60405180910390f35b61017c60048036038101906101779190611664565b61046d565b604051610189919061186f565b60405180910390f35b61019a61048b565b6040516101a791906119cc565b60405180910390f35b6101ca60048036038101906101c59190611611565b610495565b6040516101d7919061186f565b60405180910390f35b6101e861056e565b6040516101f591906119e7565b60405180910390f35b61021860048036038101906102139190611664565b610585565b604051610225919061186f565b60405180910390f35b610248600480360381019061024391906115a4565b610638565b60405161025591906119cc565b60405180910390f35b61027860048036038101906102739190611664565b6106c5565b005b610294600480360381019061028f91906115a4565b610723565b6040516102a191906119cc565b60405180910390f35b6102b261076b565b005b6102bc6108c3565b005b6102c661091d565b6040516102d39190611854565b60405180910390f35b6102e4610947565b6040516102f191906119cc565b60405180910390f35b61030261094d565b60405161030f919061188a565b60405180910390f35b610332600480360381019061032d9190611664565b6109df565b60405161033f919061186f565b60405180910390f35b610362600480360381019061035d9190611664565b610aac565b60405161036f919061186f565b60405180910390f35b610392600480360381019061038d91906115d1565b610aca565b60405161039f91906119cc565b60405180910390f35b6103c260048036038101906103bd91906115a4565b610b51565b005b6000600760009054906101000a900460ff16905090565b6060600380546103ea90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461041690611b30565b80156104635780601f1061043857610100808354040283529160200191610463565b820191906000526020600020905b81548152906001019060200180831161044657829003601f168201915b5050505050905090565b600061048161047a610d18565b8484610d20565b6001905092915050565b6000600254905090565b60006104a2848484610eeb565b610563846104ae610d18565b61055e85604051806060016040528060288152602001611e8060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610514610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b600190509392505050565b6000600560009054906101000a900460ff16905090565b600061062e610592610d18565b8461062985600160006105a3610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b610d20565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546006819055506000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600760009054906101000a900460ff1615610715576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161070c9061198c565b60405180910390fd5b61071f8282611242565b5050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610773610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f99061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600760009054906101000a900460ff1615610913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090a9061198c565b60405180910390fd5b61091b6112e7565b565b6000600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60606004805461095c90611b30565b80601f016020809104026020016040519081016040528092919081815260200182805461098890611b30565b80156109d55780601f106109aa576101008083540402835291602001916109d5565b820191906000526020600020905b8154815290600101906020018083116109b857829003601f168201915b5050505050905090565b6000610aa26109ec610d18565b84610a9d85604051806060016040528060258152602001611ea86025913960016000610a16610d18565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b610d20565b6001905092915050565b6000610ac0610ab9610d18565b8484610eeb565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610b59610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610be8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdf9061192c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610c58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c4f906118cc565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600760016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610d90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d879061196c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610e00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df7906118ec565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92583604051610ede91906119cc565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f529061194c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc2906118ac565b60405180910390fd5b610fd6838383611388565b61104181604051806060016040528060268152602001611e5a602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111809092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506110d4816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161117391906119cc565b60405180910390a3505050565b60008383111582906111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf919061188a565b60405180910390fd5b50600083856111d79190611a74565b9050809150509392505050565b60008082846111f39190611a1e565b905083811015611238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122f9061190c565b60405180910390fd5b8091505092915050565b61124a610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d09061192c565b60405180910390fd5b6112e38282611398565b5050565b6112ef610d18565b73ffffffffffffffffffffffffffffffffffffffff16600760019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461137e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113759061192c565b60405180910390fd5b61138661152c565b565b611393838383611575565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611408576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ff906119ac565b60405180910390fd5b61141460008383611388565b611429816002546111e490919063ffffffff16565b600281905550611480816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546111e490919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161152091906119cc565b60405180910390a35050565b6001600760006101000a81548160ff0219169083151502179055507fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0860405160405180910390a1565b505050565b60008135905061158981611e2b565b92915050565b60008135905061159e81611e42565b92915050565b6000602082840312156115ba576115b9611bc0565b5b60006115c88482850161157a565b91505092915050565b600080604083850312156115e8576115e7611bc0565b5b60006115f68582860161157a565b92505060206116078582860161157a565b9150509250929050565b60008060006060848603121561162a57611629611bc0565b5b60006116388682870161157a565b93505060206116498682870161157a565b925050604061165a8682870161158f565b9150509250925092565b6000806040838503121561167b5761167a611bc0565b5b60006116898582860161157a565b925050602061169a8582860161158f565b9150509250929050565b6116ad81611aa8565b82525050565b6116bc81611aba565b82525050565b60006116cd82611a02565b6116d78185611a0d565b93506116e7818560208601611afd565b6116f081611bc5565b840191505092915050565b6000611708602383611a0d565b915061171382611bd6565b604082019050919050565b600061172b602683611a0d565b915061173682611c25565b604082019050919050565b600061174e602283611a0d565b915061175982611c74565b604082019050919050565b6000611771601b83611a0d565b915061177c82611cc3565b602082019050919050565b6000611794602083611a0d565b915061179f82611cec565b602082019050919050565b60006117b7602583611a0d565b91506117c282611d15565b604082019050919050565b60006117da602483611a0d565b91506117e582611d64565b604082019050919050565b60006117fd602283611a0d565b915061180882611db3565b604082019050919050565b6000611820601f83611a0d565b915061182b82611e02565b602082019050919050565b61183f81611ae6565b82525050565b61184e81611af0565b82525050565b600060208201905061186960008301846116a4565b92915050565b600060208201905061188460008301846116b3565b92915050565b600060208201905081810360008301526118a481846116c2565b905092915050565b600060208201905081810360008301526118c5816116fb565b9050919050565b600060208201905081810360008301526118e58161171e565b9050919050565b6000602082019050818103600083015261190581611741565b9050919050565b6000602082019050818103600083015261192581611764565b9050919050565b6000602082019050818103600083015261194581611787565b9050919050565b60006020820190508181036000830152611965816117aa565b9050919050565b60006020820190508181036000830152611985816117cd565b9050919050565b600060208201905081810360008301526119a5816117f0565b9050919050565b600060208201905081810360008301526119c581611813565b9050919050565b60006020820190506119e16000830184611836565b92915050565b60006020820190506119fc6000830184611845565b92915050565b600081519050919050565b600082825260208201905092915050565b6000611a2982611ae6565b9150611a3483611ae6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115611a6957611a68611b62565b5b828201905092915050565b6000611a7f82611ae6565b9150611a8a83611ae6565b925082821015611a9d57611a9c611b62565b5b828203905092915050565b6000611ab382611ac6565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b60005b83811015611b1b578082015181840152602081019050611b00565b83811115611b2a576000848401525b50505050565b60006002820490506001821680611b4857607f821691505b60208210811415611b5c57611b5b611b91565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600080fd5b6000601f19601f8301169050919050565b7f45524332303a207472616e7366657220746f20746865207a65726f206164647260008201527f6573730000000000000000000000000000000000000000000000000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f766520746f20746865207a65726f20616464726560008201527f7373000000000000000000000000000000000000000000000000000000000000602082015250565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f45524332303a207472616e736665722066726f6d20746865207a65726f20616460008201527f6472657373000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f45524332304d696e7461626c653a206d696e74696e672069732066696e69736860008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b7f45524332303a206d696e7420746f20746865207a65726f206164647265737300600082015250565b611e3481611aa8565b8114611e3f57600080fd5b50565b611e4b81611ae6565b8114611e5657600080fd5b5056fe45524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122011d6aa32a52f13724439331c99d3ab1777561b1fe5e60286e4c692fe36f90b1064736f6c63430008070033", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "MintFinished", + "type": "event" + }, + { + "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": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finishMinting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintingFinished", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "updateBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + } + ], + "expectedNewLeafs": [ + { + "address": "0xd40Ab51C8141FaB2fe0f42c687D7bC73A9502212", + "nonce": "0", + "balance": "0", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": "5", + "balance": "99999743524000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": "4", + "balance": "199996613987000000000", + "storage": null, + "isSmartContract": false, + "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", + "bytecodeLength": 0 + }, + { + "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", + "nonce": "2", + "balance": "0", + "storage": { + "0x2091d7f8e197234fbae096c5d1c6d9a0af52e606954c1503c0e5cdc2f512f587": "0x9eb45fe565bd50b50a542132ca29a4789c64ea5d", + "0x32f01e9fb560458799c7ad5670f28e39f423ec38958fa9d2134f02919cf08eef": "0x9eb45fe565bd50b50a542132ca29a4789c64ea5d", + "0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b": "0x9eb45fe565bd50b50a542132ca29a4789c64ea5d", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x01" + }, + "isSmartContract": true, + "hashBytecode": "0x33f297f346b1ad951fda991d6b4d19b9a332b510d3ca65c3b8a7d0aebe8d06c0", + "bytecodeLength": 18864 + }, + { + "address": "0x85e844b762a271022b692cf99ce5c59ba0650ac8", + "nonce": "1", + "balance": "0", + "storage": { + "0x1ffabaa92dc53f3882949e3f1b5ada8bbe2c346d75d145c08075bc261a1eb57e": "0x29a2241af62c0000", + "0x5c9164227e4e2850b9fc759a61468f2c11426c1144a6df87b4a501cc3915e91d": "0x6124fee993bc0000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x8ac7230489e80000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5a4b434f494e410000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5a4b434f494e410000000000000000000000000000000000000000000000000e" + }, + "isSmartContract": true, + "hashBytecode": "0x6a4f4d0553421e715aade51ef1754586485a905fd5826768bc7952704a04c4ba", + "bytecodeLength": 7938 + }, + { + "address": "0x13db4b51c5174ee2366e878a367aa1d426970ade", + "nonce": "1", + "balance": "0", + "storage": { + "0x1ffabaa92dc53f3882949e3f1b5ada8bbe2c346d75d145c08075bc261a1eb57e": "0x3782dace9d900000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x02d1a51c7e00500000", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x12", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d00", + "0x5c9164227e4e2850b9fc759a61468f2c11426c1144a6df87b4a501cc3915e91d": "0x6124fee993bc0000", + "0x5eff3f6834f82409f2dbfe5bcddfb5bd62b8ea2ebf2327cfdb9577734aa9a1b2": "0x0238fd42c5cf040000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x5a4b434f494e420000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x5a4b434f494e420000000000000000000000000000000000000000000000000e" + }, + "isSmartContract": true, + "hashBytecode": "0x6a4f4d0553421e715aade51ef1754586485a905fd5826768bc7952704a04c4ba", + "bytecodeLength": 7938 + } + ] +} \ No newline at end of file diff --git a/test/vectors/src/tx-hash-ethereum/rlp.json b/test/vectors/src/tx-hash-ethereum/rlp.json new file mode 100644 index 0000000000..b3a2032b2e --- /dev/null +++ b/test/vectors/src/tx-hash-ethereum/rlp.json @@ -0,0 +1,16 @@ +[ + { + "nonce": "0x02", + "gasPrice": "0x4190AB00", + "gasLimit": "0x5208", + "to": "0x0043d60e87c5dd08C86C3123340705a1556C4719", + "value": "0x470DE4DF820000", + "data": "", + "chainId": "0x599", + "v": "0x0B3F", + "r": "0x3e5cd16f789cc06e40e19243374ae6f7bf6e9023bb8599c9eaa0bf066206bdac", + "s": "0x67afe749b374949fdb1cea34c364c3b125acc2a01b5dc9874e4a125a38fb57b1", + "hash": "0xa05bec4d932f266f68b6804de0a3ab3d1616de1f14252e3b1025f4b55a38036c", + "link": "" + } +] \ No newline at end of file diff --git a/test/vectors/statetransition.go b/test/vectors/statetransition.go index e0b07fd570..63f9448051 100644 --- a/test/vectors/statetransition.go +++ b/test/vectors/statetransition.go @@ -2,7 +2,7 @@ package vectors import ( "encoding/json" - "io/ioutil" + "io" "os" "path/filepath" ) @@ -18,7 +18,7 @@ func LoadStateTransitionTestCases(path string) ([]StateTransitionTestCase, error } defer func() { _ = jsonFile.Close() }() - bytes, err := ioutil.ReadAll(jsonFile) + bytes, err := io.ReadAll(jsonFile) if err != nil { return testCases, err } diff --git a/test/vectors/statetransition_v2.go b/test/vectors/statetransition_v2.go new file mode 100644 index 0000000000..c3036ebf89 --- /dev/null +++ b/test/vectors/statetransition_v2.go @@ -0,0 +1,36 @@ +package vectors + +import ( + "encoding/json" + "io" + "os" + "path/filepath" + "strings" +) + +// LoadStateTransitionTestCaseV2 loads the state-transition JSON file into a +// StateTransitionTestCaseV2 instance +func LoadStateTransitionTestCaseV2(path string) (StateTransitionTestCaseV2, error) { + var testCase StateTransitionTestCaseV2 + + jsonFile, err := os.Open(filepath.Clean(path)) + if err != nil { + return testCase, err + } + defer func() { _ = jsonFile.Close() }() + + bytes, err := io.ReadAll(jsonFile) + if err != nil { + return testCase, err + } + + err = json.Unmarshal(bytes, &testCase) + if err != nil { + return testCase, err + } + if testCase.Description == "" { + testCase.Description = strings.Replace(filepath.Base(path), ".json", "", 1) + } + + return testCase, nil +} diff --git a/test/vectors/vectors_v2.go b/test/vectors/vectors_v2.go new file mode 100644 index 0000000000..80638894f9 --- /dev/null +++ b/test/vectors/vectors_v2.go @@ -0,0 +1,89 @@ +package vectors + +import ( + "github.com/0xPolygonHermez/zkevm-node/merkletree" + "github.com/0xPolygonHermez/zkevm-node/state" +) + +// StateTransitionTestCaseV2 holds the metadata needed to run a state transition test +type StateTransitionTestCaseV2 struct { + Description string `json:"Description"` + Genesis []GenesisEntity `json:"genesis"` + ExpectedOldStateRoot string `json:"expectedOldStateRoot"` + ExpectedNewStateRoot string `json:"expectedNewStateRoot"` + ExpectedNewLeafs []LeafV2 `json:"expectedNewLeafs"` + Receipts []TestReceipt `json:"receipts"` + GlobalExitRoot string `json:"globalExitRoot"` + BatchL2Data string `json:"batchL2Data"` +} + +// LeafV2 represents the state of a leaf in the merkle tree +type LeafV2 struct { + Address string `json:"address"` + Balance argBigInt `json:"balance"` + Nonce string `json:"nonce"` + Storage map[string]string `json:"storage"` + IsSmartContract bool `json:"isSmartContract"` + Bytecode string `json:"bytecode"` + HashBytecode string `json:"hashBytecode"` + BytecodeLength int `json:"bytecodeLength"` +} + +// GenesisEntity represents the state of an account or smart contract when the network +// starts +type GenesisEntity struct { + Address string `json:"address"` + PvtKey *string `json:"pvtKey"` + Balance argBigInt `json:"balance"` + Nonce string `json:"nonce"` + Storage map[string]string `json:"storage"` + IsSmartContract bool `json:"isSmartContract"` + Bytecode *string `json:"bytecode"` +} + +func GenerateGenesisActions(genesis []GenesisEntity) []*state.GenesisAction { + var genesisActions []*state.GenesisAction + for _, genesisEntity := range genesis { + + if genesisEntity.Balance.String() != "0" { + action := &state.GenesisAction{ + Address: genesisEntity.Address, + Type: int(merkletree.LeafTypeBalance), + Value: genesisEntity.Balance.String(), + } + genesisActions = append(genesisActions, action) + } + + if genesisEntity.Nonce != "" && genesisEntity.Nonce != "0" { + action := &state.GenesisAction{ + Address: genesisEntity.Address, + Type: int(merkletree.LeafTypeNonce), + Value: genesisEntity.Nonce, + } + genesisActions = append(genesisActions, action) + } + + if genesisEntity.IsSmartContract && genesisEntity.Bytecode != nil && *genesisEntity.Bytecode != "0x" { + action := &state.GenesisAction{ + Address: genesisEntity.Address, + Type: int(merkletree.LeafTypeCode), + Bytecode: *genesisEntity.Bytecode, + } + genesisActions = append(genesisActions, action) + } + + if genesisEntity.IsSmartContract && len(genesisEntity.Storage) > 0 { + for storageKey, storageValue := range genesisEntity.Storage { + action := &state.GenesisAction{ + Address: genesisEntity.Address, + Type: int(merkletree.LeafTypeStorage), + StoragePosition: storageKey, + Value: storageValue, + } + genesisActions = append(genesisActions, action) + } + } + } + + return genesisActions +} diff --git a/tools/executor/docker-compose.yml b/tools/executor/docker-compose.yml index e7b811ac25..e672eccf90 100644 --- a/tools/executor/docker-compose.yml +++ b/tools/executor/docker-compose.yml @@ -10,7 +10,7 @@ services: ports: - 5432:5432 volumes: - - ../../config/initproverdb.sql:/docker-entrypoint-initdb.d/init.sql + - ../../db/scripts/init_prover_db.sql:/docker-entrypoint-initdb.d/init.sql environment: # In order to update this values, you may need to run: docker rm -f -v postgres - POSTGRES_USER=test_user diff --git a/tools/executor/main.go b/tools/executor/main.go index 43fc18c3e3..1ba488cbd3 100644 --- a/tools/executor/main.go +++ b/tools/executor/main.go @@ -4,7 +4,7 @@ import ( "context" "encoding/hex" "encoding/json" - "io/ioutil" + "os" "os/exec" "strings" "time" @@ -42,13 +42,13 @@ func main() { time.Sleep(time.Second * waitForDBSeconds) cmd = exec.Command("docker-compose", "up", "-d", "executor-tool-prover") if out, err := cmd.CombinedOutput(); err != nil { - log.Errorf("Failed to star prover: %w. %v", err, out) + log.Errorf("Failed to star prover: %v. %v", err, out) return } log.Info("DONE starting DB and prover") // Load vector file names - files, err := ioutil.ReadDir(vectorDir) + files, err := os.ReadDir(vectorDir) if err != nil { log.Errorf("Error reading directory: %v", err) return @@ -116,7 +116,7 @@ func runTestCase(ctx context.Context, genesis []genesisItem, tc testCase) error if err != nil { return err } - log.Infof("********** BATCH %d **********", tc.Requests[i].BatchNum) + log.Infof("********** BATCH %d **********", tc.Requests[i].OldBatchNum) txs, _, err := state.DecodeTxs(tc.Requests[i].BatchL2Data) if err != nil { log.Warnf("Txs are not correctly encoded") @@ -133,7 +133,7 @@ func runTestCase(ctx context.Context, genesis []genesisItem, tc testCase) error log.Infof("CntBinaries: %v", res.CntBinaries) log.Infof("CntSteps: %v", res.CntSteps) for i, txRes := range res.Responses { - log.Infof("======> TX #%d", i) + log.Infof("=====> TX #%d", i) if "0x"+hex.EncodeToString(txRes.TxHash) != txs[i].Hash().Hex() { log.Warnf("TxHash missmatch:\nexecutor: %s\ndecoded: %s", "0x"+hex.EncodeToString(txRes.TxHash), txs[i].Hash().Hex()) } else { @@ -173,7 +173,7 @@ func loadCase(vectorFileName string) ([]genesisItem, testCase, error) { tc := testCase{} gen := []genesisItem{} // Load and parse test case - f, err := ioutil.ReadFile(vectorFileName) + f, err := os.ReadFile(vectorFileName) if err != nil { return gen, tc, err } @@ -182,7 +182,7 @@ func loadCase(vectorFileName string) ([]genesisItem, testCase, error) { return gen, tc, err } // Load and parse genesis - f, err = ioutil.ReadFile(genesisDir + tc.GenesisFile) + f, err = os.ReadFile(genesisDir + tc.GenesisFile) if err != nil { return gen, tc, err } @@ -233,13 +233,13 @@ type executorRequest pb.ProcessBatchRequest func (er *executorRequest) UnmarshalJSON(data []byte) error { type jExecutorRequeststruct struct { - BatchL2Data string `json:"batchL2Data"` - GlobalExitRoot string `json:"globalExitRoot"` - BatchNum uint64 `json:"batchNum"` - OldLocalExitRoot string `json:"oldLocalExitRoot"` - OldStateRoot string `json:"oldStateRoot"` - SequencerAddr string `json:"sequencerAddr"` - Timestamp uint64 `json:"timestamp"` + BatchL2Data string `json:"batchL2Data"` + GlobalExitRoot string `json:"globalExitRoot"` + OldBatchNum uint64 `json:"oldBatchNum"` + OldAccInputHash string `json:"oldAccInputHash"` + OldStateRoot string `json:"oldStateRoot"` + SequencerAddr string `json:"sequencerAddr"` + Timestamp uint64 `json:"timestamp"` } jer := jExecutorRequeststruct{} if err := json.Unmarshal(data, &jer); err != nil { @@ -253,7 +253,7 @@ func (er *executorRequest) UnmarshalJSON(data []byte) error { if err != nil { return err } - oldLocalExitRoot, err := hex.DecodeString(strings.TrimPrefix(jer.OldLocalExitRoot, "0x")) + oldAccInputHash, err := hex.DecodeString(strings.TrimPrefix(jer.OldAccInputHash, "0x")) if err != nil { return err } @@ -263,13 +263,13 @@ func (er *executorRequest) UnmarshalJSON(data []byte) error { } req := pb.ProcessBatchRequest{ - BatchL2Data: batchL2Data, - GlobalExitRoot: globalExitRoot, - BatchNum: jer.BatchNum, - OldLocalExitRoot: oldLocalExitRoot, - OldStateRoot: oldStateRoot, - Coinbase: jer.SequencerAddr, - EthTimestamp: jer.Timestamp, + BatchL2Data: batchL2Data, + GlobalExitRoot: globalExitRoot, + OldBatchNum: jer.OldBatchNum, + OldAccInputHash: oldAccInputHash, + OldStateRoot: oldStateRoot, + Coinbase: jer.SequencerAddr, + EthTimestamp: jer.Timestamp, } *er = executorRequest(req) //nolint return nil diff --git a/tools/executor/vectors/fail-deploy-uniswap-repeated-nonce.json b/tools/executor/vectors/fail-deploy-uniswap-repeated-nonce.json index 61ce3384bf..0eab4d0a50 100644 --- a/tools/executor/vectors/fail-deploy-uniswap-repeated-nonce.json +++ b/tools/executor/vectors/fail-deploy-uniswap-repeated-nonce.json @@ -7,8 +7,8 @@ { "batchL2Data": "0xF90A7980843B9ACA008307EF0B8080B90A6560806040526005805460FF191660121790553480156200001E57600080FD5B50604051620009A5380380620009A58339810160408190526200004191620001E8565B81516200005690600390602085019062000075565B5080516200006C90600490602084019062000075565B5050506200028F565B828054620000839062000252565B90600052602060002090601F016020900481019282620000A75760008555620000F2565B82601F10620000C257805160FF1916838001178555620000F2565B82800160010185558215620000F2579182015B82811115620000F2578251825591602001919060010190620000D5565B506200010092915062000104565B5090565B5B8082111562000100576000815560010162000105565B634E487B7160E01B600052604160045260246000FD5B600082601F8301126200014357600080FD5B81516001600160401B03808211156200016057620001606200011B565B604051601F8301601F19908116603F011681019082821181831017156200018B576200018B6200011B565B81604052838152602092508683858801011115620001A857600080FD5B600091505B83821015620001CC5785820183015181830184015290820190620001AD565B83821115620001DE5760008385830101525B9695505050505050565B60008060408385031215620001FC57600080FD5B82516001600160401B03808211156200021457600080FD5B620002228683870162000131565B935060208501519150808211156200023957600080FD5B50620002488582860162000131565B9150509250929050565B600181811C908216806200026757607F821691505B602082108114156200028957634E487B7160E01B600052602260045260246000FD5B50919050565B610706806200029F6000396000F3FE608060405234801561001057600080FD5B50600436106100A95760003560E01C806342966C681161007157806342966C681461013857806370A082311461014D57806395D89B411461016D578063A0712D6814610175578063A9059CBB14610188578063DD62ED3E1461019B57600080FD5B806306FDDE03146100AE578063095EA7B3146100CC57806318160DDD146100EF57806323B872DD14610106578063313CE56714610119575B600080FD5B6100B66101C6565B6040516100C391906104EB565B60405180910390F35B6100DF6100DA36600461055C565B610254565B60405190151581526020016100C3565B6100F860005481565B6040519081526020016100C3565B6100DF610114366004610586565B6102C0565B6005546101269060FF1681565B60405160FF90911681526020016100C3565B61014B6101463660046105C2565B61039B565B005B6100F861015B3660046105DB565B60016020526000908152604090205481565B6100B6610401565B61014B6101833660046105C2565B61040E565B6100DF61019636600461055C565B61046D565B6100F86101A93660046105FD565B600260209081526000928352604080842090915290825290205481565B600380546101D390610630565B80601F01602080910402602001604051908101604052809291908181526020018280546101FF90610630565B801561024C5780601F106102215761010080835404028352916020019161024C565B820191906000526020600020905B81548152906001019060200180831161022F57829003601F168201915B505050505081565B3360008181526002602090815260408083206001600160A01B038716808552925280832085905551919290917F8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925906102AF9086815260200190565B60405180910390A350600192915050565B6001600160A01B03831660009081526002602090815260408083203384529091528120805483919083906102F5908490610681565B90915550506001600160A01B03841660009081526001602052604081208054849290610322908490610681565B90915550506001600160A01B0383166000908152600160205260408120805484929061034F908490610698565B92505081905550826001600160A01B0316846001600160A01B03166000805160206106B18339815191528460405161038991815260200190565B60405180910390A35060019392505050565B33600090815260016020526040812080548392906103BA908490610681565B92505081905550806000808282546103D29190610681565B909155505060405181815260009033906000805160206106B1833981519152906020015B60405180910390A350565B600480546101D390610630565B336000908152600160205260408120805483929061042D908490610698565B92505081905550806000808282546104459190610698565B909155505060405181815233906000906000805160206106B1833981519152906020016103F6565B3360009081526001602052604081208054839190839061048E908490610681565B90915550506001600160A01B038316600090815260016020526040812080548492906104BB908490610698565B90915550506040518281526001600160A01B0384169033906000805160206106B1833981519152906020016102AF565B600060208083528351808285015260005B81811015610518578581018301518582016040015282016104FC565B8181111561052A576000604083870101525B50601F01601F1916929092016040019392505050565B80356001600160A01B038116811461055757600080FD5B919050565B6000806040838503121561056F57600080FD5B61057883610540565B946020939093013593505050565B60008060006060848603121561059B57600080FD5B6105A484610540565B92506105B260208501610540565B9150604084013590509250925092565B6000602082840312156105D457600080FD5B5035919050565B6000602082840312156105ED57600080FD5B6105F682610540565B9392505050565B6000806040838503121561061057600080FD5B61061983610540565B915061062760208401610540565B90509250929050565B600181811C9082168061064457607F821691505B6020821081141561066557634E487B7160E01B600052602260045260246000FD5B50919050565B634E487B7160E01B600052601160045260246000FD5B6000828210156106935761069361066B565B500390565B600082198211156106AB576106AB61066B565B50019056FEDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EFA26469706673582212200BC4422A3C70571F82D7AFF8AD633B2BE9F8E29FF037EAEAD009019ED70ED47864736F6C634300080C00330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064120434F494E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000341434F00000000000000000000000000000000000000000000000000000000008203E880801F132E59D67DC90EF8066E07131840B0C9B5F56987B14253A12E588E185DD1AD01D5FD713C784D0980DF79FBF8CC3CD63B27DECB90D6BADB575FD08DBAECADC11C", "globalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "batchNum": 1, - "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "oldBatchNum": 0, + "oldAccInputhHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldStateRoot": "0xC8F751215E3F69B83361AF8CDF8C657773743AF845E313659F6A8189B098E038", "sequencerAddr": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "timestamp": 1661352560 @@ -16,8 +16,8 @@ { "batchL2Data": "0xf90a7901843b9aca008307ef0b8080b90a6560806040526005805460ff191660121790553480156200001e57600080fd5b50604051620009a5380380620009a58339810160408190526200004191620001e8565b81516200005690600390602085019062000075565b5080516200006c90600490602084019062000075565b5050506200028f565b828054620000839062000252565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b60008060408385031215620001fc57600080fd5b82516001600160401b03808211156200021457600080fd5b620002228683870162000131565b935060208501519150808211156200023957600080fd5b50620002488582860162000131565b9150509250929050565b600181811c908216806200026757607f821691505b602082108114156200028957634e487b7160e01b600052602260045260246000fd5b50919050565b610706806200029f6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806342966c681161007157806342966c681461013857806370a082311461014d57806395d89b411461016d578063a0712d6814610175578063a9059cbb14610188578063dd62ed3e1461019b57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610106578063313ce56714610119575b600080fd5b6100b66101c6565b6040516100c391906104eb565b60405180910390f35b6100df6100da36600461055c565b610254565b60405190151581526020016100c3565b6100f860005481565b6040519081526020016100c3565b6100df610114366004610586565b6102c0565b6005546101269060ff1681565b60405160ff90911681526020016100c3565b61014b6101463660046105c2565b61039b565b005b6100f861015b3660046105db565b60016020526000908152604090205481565b6100b6610401565b61014b6101833660046105c2565b61040e565b6100df61019636600461055c565b61046d565b6100f86101a93660046105fd565b600260209081526000928352604080842090915290825290205481565b600380546101d390610630565b80601f01602080910402602001604051908101604052809291908181526020018280546101ff90610630565b801561024c5780601f106102215761010080835404028352916020019161024c565b820191906000526020600020905b81548152906001019060200180831161022f57829003601f168201915b505050505081565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906102af9086815260200190565b60405180910390a350600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120805483919083906102f5908490610681565b90915550506001600160a01b03841660009081526001602052604081208054849290610322908490610681565b90915550506001600160a01b0383166000908152600160205260408120805484929061034f908490610698565b92505081905550826001600160a01b0316846001600160a01b03166000805160206106b18339815191528460405161038991815260200190565b60405180910390a35060019392505050565b33600090815260016020526040812080548392906103ba908490610681565b92505081905550806000808282546103d29190610681565b909155505060405181815260009033906000805160206106b1833981519152906020015b60405180910390a350565b600480546101d390610630565b336000908152600160205260408120805483929061042d908490610698565b92505081905550806000808282546104459190610698565b909155505060405181815233906000906000805160206106b1833981519152906020016103f6565b3360009081526001602052604081208054839190839061048e908490610681565b90915550506001600160a01b038316600090815260016020526040812080548492906104bb908490610698565b90915550506040518281526001600160a01b0384169033906000805160206106b1833981519152906020016102af565b600060208083528351808285015260005b81811015610518578581018301518582016040015282016104fc565b8181111561052a576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461055757600080fd5b919050565b6000806040838503121561056f57600080fd5b61057883610540565b946020939093013593505050565b60008060006060848603121561059b57600080fd5b6105a484610540565b92506105b260208501610540565b9150604084013590509250925092565b6000602082840312156105d457600080fd5b5035919050565b6000602082840312156105ed57600080fd5b6105f682610540565b9392505050565b6000806040838503121561061057600080fd5b61061983610540565b915061062760208401610540565b90509250929050565b600181811c9082168061064457607f821691505b6020821081141561066557634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156106935761069361066b565b500390565b600082198211156106ab576106ab61066b565b50019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200bc4422a3c70571f82d7aff8ad633b2be9f8e29ff037eaead009019ed70ed47864736f6c634300080c00330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000064220434f494e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000342434f00000000000000000000000000000000000000000000000000000000008203e880809219d7a726ca241d9eb518621ab4a2f6e496667e61354b3eceffe1e302c7bc02434a43a87a25a0dc372cb13b15c1014fddeb88954c7d8113e25c9bb0871b52131cf9083102843b9aca008307995b8080b9081d606060405260408051908101604052600d81527f57726170706564204574686572000000000000000000000000000000000000006020820152600090805161004b9291602001906100b1565b5060408051908101604052600481527f5745544800000000000000000000000000000000000000000000000000000000602082015260019080516100939291602001906100b1565b506002805460ff1916601217905534156100ac57600080fd5b61014c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100f257805160ff191683800117855561011f565b8280016001018555821561011f579182015b8281111561011f578251825591602001919060010190610104565b5061012b92915061012f565b5090565b61014991905b8082111561012b5760008155600101610135565b90565b6106c28061015b6000396000f3006060604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461017857806323b872dd1461019d5780632e1a7d4d146101c5578063313ce567146101db57806370a082311461020457806395d89b4114610223578063a9059cbb14610236578063d0e30db0146100ae578063dd62ed3e14610258575b6100b661027d565b005b34156100c357600080fd5b6100cb6102d3565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101075780820151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610164600160a060020a0360043516602435610371565b604051901515815260200160405180910390f35b341561018357600080fd5b61018b6103dd565b60405190815260200160405180910390f35b34156101a857600080fd5b610164600160a060020a03600435811690602435166044356103eb565b34156101d057600080fd5b6100b6600435610531565b34156101e657600080fd5b6101ee6105df565b60405160ff909116815260200160405180910390f35b341561020f57600080fd5b61018b600160a060020a03600435166105e8565b341561022e57600080fd5b6100cb6105fa565b341561024157600080fd5b610164600160a060020a0360043516602435610665565b341561026357600080fd5b61018b600160a060020a0360043581169060243516610679565b600160a060020a033316600081815260036020526040908190208054349081019091557fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c915190815260200160405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103695780601f1061033e57610100808354040283529160200191610369565b820191906000526020600020905b81548152906001019060200180831161034c57829003601f168201915b505050505081565b600160a060020a03338116600081815260046020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b600160a060020a0330163190565b600160a060020a0383166000908152600360205260408120548290101561041157600080fd5b33600160a060020a031684600160a060020a03161415801561045b5750600160a060020a038085166000908152600460209081526040808320339094168352929052205460001914155b156104c257600160a060020a03808516600090815260046020908152604080832033909416835292905220548290101561049457600080fd5b600160a060020a03808516600090815260046020908152604080832033909416835292905220805483900390555b600160a060020a038085166000818152600360205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060019392505050565b600160a060020a0333166000908152600360205260409020548190101561055757600080fd5b600160a060020a033316600081815260036020526040908190208054849003905582156108fc0290839051600060405180830381858888f19350505050151561059f57600080fd5b33600160a060020a03167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405190815260200160405180910390a250565b60025460ff1681565b60036020526000908152604090205481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103695780601f1061033e57610100808354040283529160200191610369565b60006106723384846103eb565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a7230582019bb09a6b1cf7b186470ffe79d111d70bf336519c38a54538be82f940b6a863500298203e8808063a56602d7a213782e53b96cbe16a1cf75d8180342ab85bb018eb3eded5f7cb542c4079f00a85182d638c7aac77a5418392a07ce03324e869f1ddcc420c6d0b01c", "globalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "batchNum": 2, - "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "oldBatchNum": 1, + "oldAccInputhHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldStateRoot": "0xd69b140edd763769df5cc4cfa314d7c4055b5a96d15001954a3841965057e7d0", "sequencerAddr": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "timestamp": 1661520575 @@ -25,8 +25,8 @@ { "batchL2Data": "0xf90a7903843b9aca008307ef238080b90a6560806040526005805460ff191660121790553480156200001e57600080fd5b50604051620009a5380380620009a58339810160408190526200004191620001e8565b81516200005690600390602085019062000075565b5080516200006c90600490602084019062000075565b5050506200028f565b828054620000839062000252565b90600052602060002090601f016020900481019282620000a75760008555620000f2565b82601f10620000c257805160ff1916838001178555620000f2565b82800160010185558215620000f2579182015b82811115620000f2578251825591602001919060010190620000d5565b506200010092915062000104565b5090565b5b8082111562000100576000815560010162000105565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014357600080fd5b81516001600160401b03808211156200016057620001606200011b565b604051601f8301601f19908116603f011681019082821181831017156200018b576200018b6200011b565b81604052838152602092508683858801011115620001a857600080fd5b600091505b83821015620001cc5785820183015181830184015290820190620001ad565b83821115620001de5760008385830101525b9695505050505050565b60008060408385031215620001fc57600080fd5b82516001600160401b03808211156200021457600080fd5b620002228683870162000131565b935060208501519150808211156200023957600080fd5b50620002488582860162000131565b9150509250929050565b600181811c908216806200026757607f821691505b602082108114156200028957634e487b7160e01b600052602260045260246000fd5b50919050565b610706806200029f6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c806342966c681161007157806342966c681461013857806370a082311461014d57806395d89b411461016d578063a0712d6814610175578063a9059cbb14610188578063dd62ed3e1461019b57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610106578063313ce56714610119575b600080fd5b6100b66101c6565b6040516100c391906104eb565b60405180910390f35b6100df6100da36600461055c565b610254565b60405190151581526020016100c3565b6100f860005481565b6040519081526020016100c3565b6100df610114366004610586565b6102c0565b6005546101269060ff1681565b60405160ff90911681526020016100c3565b61014b6101463660046105c2565b61039b565b005b6100f861015b3660046105db565b60016020526000908152604090205481565b6100b6610401565b61014b6101833660046105c2565b61040e565b6100df61019636600461055c565b61046d565b6100f86101a93660046105fd565b600260209081526000928352604080842090915290825290205481565b600380546101d390610630565b80601f01602080910402602001604051908101604052809291908181526020018280546101ff90610630565b801561024c5780601f106102215761010080835404028352916020019161024c565b820191906000526020600020905b81548152906001019060200180831161022f57829003601f168201915b505050505081565b3360008181526002602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906102af9086815260200190565b60405180910390a350600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120805483919083906102f5908490610681565b90915550506001600160a01b03841660009081526001602052604081208054849290610322908490610681565b90915550506001600160a01b0383166000908152600160205260408120805484929061034f908490610698565b92505081905550826001600160a01b0316846001600160a01b03166000805160206106b18339815191528460405161038991815260200190565b60405180910390a35060019392505050565b33600090815260016020526040812080548392906103ba908490610681565b92505081905550806000808282546103d29190610681565b909155505060405181815260009033906000805160206106b1833981519152906020015b60405180910390a350565b600480546101d390610630565b336000908152600160205260408120805483929061042d908490610698565b92505081905550806000808282546104459190610698565b909155505060405181815233906000906000805160206106b1833981519152906020016103f6565b3360009081526001602052604081208054839190839061048e908490610681565b90915550506001600160a01b038316600090815260016020526040812080548492906104bb908490610698565b90915550506040518281526001600160a01b0384169033906000805160206106b1833981519152906020016102af565b600060208083528351808285015260005b81811015610518578581018301518582016040015282016104fc565b8181111561052a576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461055757600080fd5b919050565b6000806040838503121561056f57600080fd5b61057883610540565b946020939093013593505050565b60008060006060848603121561059b57600080fd5b6105a484610540565b92506105b260208501610540565b9150604084013590509250925092565b6000602082840312156105d457600080fd5b5035919050565b6000602082840312156105ed57600080fd5b6105f682610540565b9392505050565b6000806040838503121561061057600080fd5b61061983610540565b915061062760208401610540565b90509250929050565b600181811c9082168061064457607f821691505b6020821081141561066557634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156106935761069361066b565b500390565b600082198211156106ab576106ab61066b565b50019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200bc4422a3c70571f82d7aff8ad633b2be9f8e29ff037eaead009019ed70ed47864736f6c634300080c0033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000007555344432f2f4300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000455534443000000000000000000000000000000000000000000000000000000008203e88080480b4da0ff61482287fb596871a50653fb9b19ca5cd428b8ea7981254309aa9d5940a9c6ef1b247ae2f7baeae4483e5dd396598e4a5232a63cf3b40b51af3a831cf84a04843b9aca0083010936948464135c8f25da09e49bc8782676a84730c318bc80a4a0712d6800000000000000000000000000000000000000000000d3c21bcecceda10000008203e88080f91056f279f0923daea87bdfab787751965a0ace3bd48167a37add08b64850311eb6b32e625a91798d3d6db00a2a98e51a47e53e728d85565766c47155f4655f1bf84a05843b9aca00830109369471c95911e9a5d330f4d621842ec243ee1343292e80a4a0712d6800000000000000000000000000000000000000000000d3c21bcecceda10000008203e88080e428757cf13b8c826944993773e8a04416bafcd4c5e952d229b865341016ea506e73cd0ec51add056e5c547544877c1c178821012e1b57ee199acd2f0c32922b1bf84a06843b9aca008301093694712516e61c8b383df4a63cfe83d7701bce54b03e80a4a0712d6800000000000000000000000000000000000000000000d3c21bcecceda10000008203e88080dd8599b59b4996ada25546db7d7a4275e7f209a4b45afd3129420c9f8ec960576c65e019c3bf824cdd1c440e95d64d7cdc970070ce36dc635858ce07ab112fda1bf007843b9aca0082b00a94948b3c65b89df0b4894abe91e6d02fe579834f8f872386f26fc1000084d0e30db08203e880807745ade3b49013e01a2b7d98ee00aa1d9ffe2b15aeef2893b969224d8502ac3a796f65a5d75b358ee8ea76a4169d1ca8e4808413dc45def56643ce15559250861cf9617f08843b9aca008352fe788080b9616b60a060405234801561001057600080fd5b503060601b608052600380546001600160a01b031916339081179091556040516000907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c908290a36101f4600081815260046020527ffb8cf1d12598d1a039dd1d106665851a96aadf67d0d9ed76fceea282119208b7805462ffffff1916600a90811790915560405190929160008051602061614b83398151915291a3610bb8600081815260046020527f72dffa9b822156d9cf4b0090fa0b656bcb9cc2b2c60eb6acfc20a34f54b31743805462ffffff1916603c90811790915560405190929160008051602061614b83398151915291a3612710600081815260046020527f8cc740d51daa94ff54f33bd779c2d20149f524c340519b49181be5a08615f829805462ffffff191660c890811790915560405190929160008051602061614b83398151915291a360805160601c615fd7610174600039806105515250615fd76000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063890357301161005b578063890357301461013b5780638a7c195f146101855780638da5cb5b146101b0578063a1671295146101b85761007d565b806313af4035146100825780631698ee82146100aa57806322afcccb14610102575b600080fd5b6100a86004803603602081101561009857600080fd5b50356001600160a01b03166101f4565b005b6100e6600480360360608110156100c057600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff16610267565b604080516001600160a01b039092168252519081900360200190f35b6101246004803603602081101561011857600080fd5b503562ffffff16610293565b6040805160029290920b8252519081900360200190f35b6101436102a8565b604080516001600160a01b0396871681529486166020860152929094168383015262ffffff16606083015260029290920b608082015290519081900360a00190f35b6100a86004803603604081101561019b57600080fd5b5062ffffff813516906020013560020b6102de565b6100e66103a1565b6100e6600480360360608110156101ce57600080fd5b5080356001600160a01b03908116916020810135909116906040013562ffffff166103b0565b6003546001600160a01b0316331461020b57600080fd5b6003546040516001600160a01b038084169216907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c90600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60056020908152600093845260408085208252928452828420905282529020546001600160a01b031681565b60046020526000908152604090205460020b81565b600054600154600280546001600160a01b03938416939283169281169162ffffff600160a01b83041691600160b81b9004900b85565b6003546001600160a01b031633146102f557600080fd5b620f42408262ffffff161061030957600080fd5b60008160020b13801561032057506140008160020b125b61032957600080fd5b62ffffff8216600090815260046020526040902054600290810b900b1561034f57600080fd5b62ffffff828116600081815260046020526040808220805462ffffff1916600287900b958616179055517fc66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc9190a35050565b6003546001600160a01b031681565b60006103ba610546565b826001600160a01b0316846001600160a01b031614156103d957600080fd5b600080846001600160a01b0316866001600160a01b0316106103fc5784866103ff565b85855b90925090506001600160a01b03821661041757600080fd5b62ffffff8416600090815260046020526040902054600290810b9081900b61043e57600080fd5b6001600160a01b0383811660009081526005602090815260408083208685168452825280832062ffffff8a168452909152902054161561047d57600080fd5b61048a308484888561057d565b6001600160a01b03808516600081815260056020818152604080842089871680865290835281852062ffffff8e168087529084528286208054988a166001600160a01b0319998a1681179091558287529484528286208787528452828620818752845294829020805490971684179096558051600289900b815291820192909252815195995091947f783cca1c0412dd0d695e784568c96da2e9c22ff989357a2e8b1d9b2b4e6b71189281900390910190a45050509392505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461057b57600080fd5b565b6040805160a0810182526001600160a01b03878116808352878216602080850182905292881684860181905262ffffff888116606080880182905260028a810b6080998a01819052600080546001600160a01b03199081169099178155600180548a1689179055825490981686177fffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffff16600160a01b8502177fffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffff16600160b81b91830b9095160293909317909255875180870194909452838801929092528281019190915285518083039091018152930193849052825192909101919091209091610686906106f5565b8190604051809103906000f59050801580156106a6573d6000803e3d6000fd5b50600080546001600160a01b0319908116909155600180549091169055600280547fffffffffffff00000000000000000000000000000000000000000000000000001690559695505050505050565b6158c8806107038339019056fe6101606040523480156200001257600080fd5b503060601b60805260408051630890357360e41b81529051600091339163890357309160048082019260a092909190829003018186803b1580156200005657600080fd5b505afa1580156200006b573d6000803e3d6000fd5b505050506040513d60a08110156200008257600080fd5b508051602080830151604084015160608086015160809096015160e896871b6001600160e81b0319166101005291811b6001600160601b031990811660e05292811b831660c0529390931b1660a052600282810b900b90921b610120529150620000f79082906200010f811b62002b8417901c565b60801b6001600160801b03191661014052506200017d565b60008082600281900b620d89e719816200012557fe5b05029050600083600281900b620d89e8816200013d57fe5b0502905060008460020b83830360020b816200015557fe5b0560010190508062ffffff166001600160801b038016816200017357fe5b0495945050505050565b60805160601c60a05160601c60c05160601c60e05160601c6101005160e81c6101205160e81c6101405160801c61567e6200024a60003980611fee5280614b5f5280614b96525080610c0052806128fd5280614bca5280614bfc525080610cef52806119cb5280611a0252806129455250806111c75280611a855280611ef4528061244452806129215280613e6b5250806108d252806112f55280611a545280611e8e52806123be5280613d2252508061207b528061227d52806128d9525080612bfb525061567e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806370cf754a116100ee578063c45a015511610097578063ddca3f4311610071578063ddca3f4314610800578063f305839914610820578063f30dba9314610828578063f637731d146108aa576101ae565b8063c45a0155146107d1578063d0c93a7c146107d9578063d21220a7146107f8576101ae565b8063883bdbfd116100c8578063883bdbfd14610633578063a34123a71461073c578063a38807f214610776576101ae565b806370cf754a146105c65780638206a4d1146105ce57806385b66729146105f6576101ae565b80633850c7bd1161015b578063490e6cbc11610135578063490e6cbc146104705780634f1eb3d8146104fc578063514ea4bf1461054d5780635339c296146105a6576101ae565b80633850c7bd1461035b5780633c8a7d8d146103b45780634614131914610456576101ae565b80631ad8b03b1161018c5780631ad8b03b146102aa578063252c09d7146102e157806332148f6714610338576101ae565b80630dfe1681146101b3578063128acb08146101d75780631a68650214610286575b600080fd5b6101bb6108d0565b604080516001600160a01b039092168252519081900360200190f35b61026d600480360360a08110156101ed57600080fd5b6001600160a01b0382358116926020810135151592604082013592606083013516919081019060a08101608082013564010000000081111561022e57600080fd5b82018360208201111561024057600080fd5b8035906020019184600183028401116401000000008311171561026257600080fd5b5090925090506108f4565b6040805192835260208301919091528051918290030190f35b61028e6114ad565b604080516001600160801b039092168252519081900360200190f35b6102b26114bc565b60405180836001600160801b03168152602001826001600160801b031681526020019250505060405180910390f35b6102fe600480360360208110156102f757600080fd5b50356114d6565b6040805163ffffffff909516855260069390930b60208501526001600160a01b039091168383015215156060830152519081900360800190f35b6103596004803603602081101561034e57600080fd5b503561ffff1661151c565b005b610363611616565b604080516001600160a01b03909816885260029690960b602088015261ffff9485168787015292841660608701529216608085015260ff90911660a0840152151560c0830152519081900360e00190f35b61026d600480360360a08110156103ca57600080fd5b6001600160a01b03823516916020810135600290810b92604083013590910b916001600160801b036060820135169181019060a08101608082013564010000000081111561041757600080fd5b82018360208201111561042957600080fd5b8035906020019184600183028401116401000000008311171561044b57600080fd5b509092509050611666565b61045e611922565b60408051918252519081900360200190f35b6103596004803603608081101561048657600080fd5b6001600160a01b0382351691602081013591604082013591908101906080810160608201356401000000008111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111640100000000831117156104f157600080fd5b509092509050611928565b6102b2600480360360a081101561051257600080fd5b506001600160a01b03813516906020810135600290810b91604081013590910b906001600160801b0360608201358116916080013516611d83565b61056a6004803603602081101561056357600080fd5b5035611f9d565b604080516001600160801b0396871681526020810195909552848101939093529084166060840152909216608082015290519081900360a00190f35b61045e600480360360208110156105bc57600080fd5b503560010b611fda565b61028e611fec565b610359600480360360408110156105e457600080fd5b5060ff81358116916020013516612010565b6102b26004803603606081101561060c57600080fd5b506001600160a01b03813516906001600160801b036020820135811691604001351661220f565b6106a36004803603602081101561064957600080fd5b81019060208101813564010000000081111561066457600080fd5b82018360208201111561067657600080fd5b8035906020019184602083028401116401000000008311171561069857600080fd5b5090925090506124dc565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156106e75781810151838201526020016106cf565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561072657818101518382015260200161070e565b5050505090500194505050505060405180910390f35b61026d6004803603606081101561075257600080fd5b508035600290810b91602081013590910b90604001356001600160801b0316612569565b6107a06004803603604081101561078c57600080fd5b508035600290810b9160200135900b6126e0565b6040805160069490940b84526001600160a01b03909216602084015263ffffffff1682820152519081900360600190f35b6101bb6128d7565b6107e16128fb565b6040805160029290920b8252519081900360200190f35b6101bb61291f565b610808612943565b6040805162ffffff9092168252519081900360200190f35b61045e612967565b6108486004803603602081101561083e57600080fd5b503560020b61296d565b604080516001600160801b039099168952600f9790970b602089015287870195909552606087019390935260069190910b60808601526001600160a01b031660a085015263ffffffff1660c0840152151560e083015251908190036101000190f35b610359600480360360208110156108c057600080fd5b50356001600160a01b03166129db565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000806108ff612bf0565b85610936576040805162461bcd60e51b8152602060048201526002602482015261415360f01b604482015290519081900360640190fd5b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602083015261ffff600160b81b8204811693830193909352600160c81b810483166060830152600160d81b8104909216608082015260ff600160e81b8304811660a0830152600160f01b909204909116151560c082018190526109ef576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b87610a3a5780600001516001600160a01b0316866001600160a01b0316118015610a35575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038716105b610a6c565b80600001516001600160a01b0316866001600160a01b0316108015610a6c57506401000276a36001600160a01b038716115b610aa3576040805162461bcd60e51b815260206004820152600360248201526214d41360ea1b604482015290519081900360640190fd5b6000805460ff60f01b191681556040805160c08101909152808a610ad25760048460a0015160ff16901c610ae5565b60108460a0015160ff1681610ae357fe5b065b60ff1681526004546001600160801b03166020820152604001610b06612c27565b63ffffffff168152602001600060060b815260200160006001600160a01b031681526020016000151581525090506000808913905060006040518060e001604052808b81526020016000815260200185600001516001600160a01b03168152602001856020015160020b81526020018c610b8257600254610b86565b6001545b815260200160006001600160801b0316815260200184602001516001600160801b031681525090505b805115801590610bd55750886001600160a01b031681604001516001600160a01b031614155b15610f9f57610be261560e565b60408201516001600160a01b031681526060820151610c25906006907f00000000000000000000000000000000000000000000000000000000000000008f612c2b565b15156040830152600290810b810b60208301819052620d89e719910b1215610c5657620d89e7196020820152610c75565b6020810151620d89e860029190910b1315610c7557620d89e860208201525b610c828160200151612d6d565b6001600160a01b031660608201526040820151610d13908d610cbc578b6001600160a01b031683606001516001600160a01b031611610cd6565b8b6001600160a01b031683606001516001600160a01b0316105b610ce4578260600151610ce6565b8b5b60c085015185517f000000000000000000000000000000000000000000000000000000000000000061309f565b60c085015260a084015260808301526001600160a01b031660408301528215610d7557610d498160c00151826080015101613291565b825103825260a0810151610d6b90610d6090613291565b6020840151906132a7565b6020830152610db0565b610d828160a00151613291565b825101825260c08101516080820151610daa91610d9f9101613291565b6020840151906132c3565b60208301525b835160ff1615610df6576000846000015160ff168260c0015181610dd057fe5b60c0840180519290910491829003905260a0840180519091016001600160801b03169052505b60c08201516001600160801b031615610e3557610e298160c00151600160801b8460c001516001600160801b03166132d9565b60808301805190910190525b80606001516001600160a01b031682604001516001600160a01b03161415610f5e57806040015115610f35578360a00151610ebf57610e9d846040015160008760200151886040015188602001518a606001516008613389909695949392919063ffffffff16565b6001600160a01b03166080860152600690810b900b6060850152600160a08501525b6000610f0b82602001518e610ed657600154610edc565b84608001515b8f610eeb578560800151610eef565b6002545b608089015160608a015160408b0151600595949392919061351c565b90508c15610f17576000035b610f258360c00151826135ef565b6001600160801b031660c0840152505b8b610f44578060200151610f4d565b60018160200151035b600290810b900b6060830152610f99565b80600001516001600160a01b031682604001516001600160a01b031614610f9957610f8c82604001516136a5565b600290810b900b60608301525b50610baf565b836020015160020b816060015160020b1461107a57600080610fed86604001518660400151886020015188602001518a606001518b6080015160086139d1909695949392919063ffffffff16565b604085015160608601516000805461ffff60c81b1916600160c81b61ffff958616021761ffff60b81b1916600160b81b95909416949094029290921762ffffff60a01b1916600160a01b62ffffff60029490940b93909316929092029190911773ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116179055506110ac9050565b60408101516000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039092169190911790555b8060c001516001600160801b031683602001516001600160801b0316146110f25760c0810151600480546001600160801b0319166001600160801b039092169190911790555b8a1561114257608081015160015560a08101516001600160801b03161561113d5760a0810151600380546001600160801b031981166001600160801b03918216909301169190911790555b611188565b608081015160025560a08101516001600160801b0316156111885760a0810151600380546001600160801b03808216600160801b92839004821690940116029190911790555b8115158b1515146111a157602081015181518b036111ae565b80600001518a0381602001515b90965094508a156112e75760008512156111f0576111f07f00000000000000000000000000000000000000000000000000000000000000008d87600003613b86565b60006111fa613cd4565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b5050505061129e613cd4565b6112a88289613e0d565b11156112e1576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b50611411565b600086121561131e5761131e7f00000000000000000000000000000000000000000000000000000000000000008d88600003613b86565b6000611328613e1d565b9050336001600160a01b031663fa461e3388888c8c6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156113ac57600080fd5b505af11580156113c0573d6000803e3d6000fd5b505050506113cc613e1d565b6113d68288613e0d565b111561140f576040805162461bcd60e51b815260206004820152600360248201526249494160e81b604482015290519081900360640190fd5b505b60408082015160c083015160608085015184518b8152602081018b90526001600160a01b03948516818701526001600160801b039093169183019190915260020b60808201529151908e169133917fc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca679181900360a00190a350506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b6004546001600160801b031681565b6003546001600160801b0380821691600160801b90041682565b60088161ffff81106114e757600080fd5b015463ffffffff81169150640100000000810460060b90600160581b81046001600160a01b031690600160f81b900460ff1684565b600054600160f01b900460ff16611560576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611575612bf0565b60008054600160d81b900461ffff169061159160088385613eb5565b6000805461ffff808416600160d81b810261ffff60d81b19909316929092179092559192508316146115fe576040805161ffff80851682528316602082015281517fac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a929181900390910190a15b50506000805460ff60f01b1916600160f01b17905550565b6000546001600160a01b03811690600160a01b810460020b9061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b8204811691600160f01b90041687565b600080548190600160f01b900460ff166116ad576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b191690556001600160801b0385166116cd57600080fd5b60008061171b60405180608001604052808c6001600160a01b031681526020018b60020b81526020018a60020b81526020016117118a6001600160801b0316613f58565b600f0b9052613f69565b9250925050819350809250600080600086111561173d5761173a613cd4565b91505b841561174e5761174b613e1d565b90505b336001600160a01b031663d348799787878b8b6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b1580156117d057600080fd5b505af11580156117e4573d6000803e3d6000fd5b50505050600086111561183b576117f9613cd4565b6118038388613e0d565b111561183b576040805162461bcd60e51b815260206004820152600260248201526104d360f41b604482015290519081900360640190fd5b841561188b57611849613e1d565b6118538287613e0d565b111561188b576040805162461bcd60e51b81526020600482015260026024820152614d3160f01b604482015290519081900360640190fd5b8960020b8b60020b8d6001600160a01b03167f7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde338d8b8b60405180856001600160a01b03168152602001846001600160801b0316815260200183815260200182815260200194505050505060405180910390a450506000805460ff60f01b1916600160f01b17905550919890975095505050505050565b60025481565b600054600160f01b900460ff1661196c576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19169055611981612bf0565b6004546001600160801b0316806119c3576040805162461bcd60e51b81526020600482015260016024820152601360fa1b604482015290519081900360640190fd5b60006119f8867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a2f867f000000000000000000000000000000000000000000000000000000000000000062ffffff16620f42406141a9565b90506000611a3b613cd4565b90506000611a47613e1d565b90508815611a7a57611a7a7f00000000000000000000000000000000000000000000000000000000000000008b8b613b86565b8715611aab57611aab7f00000000000000000000000000000000000000000000000000000000000000008b8a613b86565b336001600160a01b031663e9cbafb085858a8a6040518563ffffffff1660e01b815260040180858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050600060405180830381600087803b158015611b2d57600080fd5b505af1158015611b41573d6000803e3d6000fd5b505050506000611b4f613cd4565b90506000611b5b613e1d565b905081611b688588613e0d565b1115611ba0576040805162461bcd60e51b8152602060048201526002602482015261046360f41b604482015290519081900360640190fd5b80611bab8487613e0d565b1115611be3576040805162461bcd60e51b8152602060048201526002602482015261463160f01b604482015290519081900360640190fd5b8382038382038115611c725760008054600160e81b9004600f16908115611c16578160ff168481611c1057fe5b04611c19565b60005b90506001600160801b03811615611c4c57600380546001600160801b038082168401166001600160801b03199091161790555b611c66818503600160801b8d6001600160801b03166132d9565b60018054909101905550505b8015611cfd5760008054600160e81b900460041c600f16908115611ca2578160ff168381611c9c57fe5b04611ca5565b60005b90506001600160801b03811615611cd757600380546001600160801b03600160801b8083048216850182160291161790555b611cf1818403600160801b8d6001600160801b03166132d9565b60028054909101905550505b8d6001600160a01b0316336001600160a01b03167fbdbdb71d7860376ba52b25a5028beea23581364a40522f6bcfb86bb1f2dca6338f8f86866040518085815260200184815260200183815260200182815260200194505050505060405180910390a350506000805460ff60f01b1916600160f01b179055505050505050505050505050565b600080548190600160f01b900460ff16611dca576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b19168155611de460073389896141e3565b60038101549091506001600160801b0390811690861611611e055784611e14565b60038101546001600160801b03165b60038201549093506001600160801b03600160801b909104811690851611611e3c5783611e52565b6003810154600160801b90046001600160801b03165b91506001600160801b03831615611eb7576003810180546001600160801b031981166001600160801b03918216869003821617909155611eb7907f0000000000000000000000000000000000000000000000000000000000000000908a908616613b86565b6001600160801b03821615611f1d576003810180546001600160801b03600160801b808304821686900382160291811691909117909155611f1d907f0000000000000000000000000000000000000000000000000000000000000000908a908516613b86565b604080516001600160a01b038a1681526001600160801b0380861660208301528416818301529051600288810b92908a900b9133917f70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0919081900360600190a4506000805460ff60f01b1916600160f01b17905590969095509350505050565b60076020526000908152604090208054600182015460028301546003909301546001600160801b0392831693919281811691600160801b90041685565b60066020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b600054600160f01b900460ff16612054576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156120c157600080fd5b505afa1580156120d5573d6000803e3d6000fd5b505050506040513d60208110156120eb57600080fd5b50516001600160a01b0316331461210157600080fd5b60ff82161580612124575060048260ff16101580156121245750600a8260ff1611155b801561214e575060ff8116158061214e575060048160ff161015801561214e5750600a8160ff1611155b61215757600080fd5b60008054610ff0600484901b16840160ff908116600160e81b9081027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841617909355919004167f973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b1336010826040805160ff9390920683168252600f600486901c16602083015286831682820152918516606082015290519081900360800190a150506000805460ff60f01b1916600160f01b17905550565b600080548190600160f01b900460ff16612256576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916905560408051638da5cb5b60e01b815290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638da5cb5b916004808301926020929190829003018186803b1580156122c357600080fd5b505afa1580156122d7573d6000803e3d6000fd5b505050506040513d60208110156122ed57600080fd5b50516001600160a01b0316331461230357600080fd5b6003546001600160801b039081169085161161231f578361232c565b6003546001600160801b03165b6003549092506001600160801b03600160801b9091048116908416116123525782612366565b600354600160801b90046001600160801b03165b90506001600160801b038216156123e7576003546001600160801b038381169116141561239557600019909101905b600380546001600160801b031981166001600160801b039182168590038216179091556123e7907f00000000000000000000000000000000000000000000000000000000000000009087908516613b86565b6001600160801b0381161561246d576003546001600160801b03828116600160801b90920416141561241857600019015b600380546001600160801b03600160801b80830482168590038216029181169190911790915561246d907f00000000000000000000000000000000000000000000000000000000000000009087908416613b86565b604080516001600160801b0380851682528316602082015281516001600160a01b0388169233927f596b573906218d3411850b26a6b437d6c4522fdb43d2d2386263f86d50b8b151929081900390910190a36000805460ff60f01b1916600160f01b1790559094909350915050565b6060806124e7612bf0565b61255e6124f2612c27565b858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525054600454600896959450600160a01b820460020b935061ffff600160b81b8304811693506001600160801b0390911691600160c81b900416614247565b915091509250929050565b600080548190600160f01b900460ff166125b0576040805162461bcd60e51b81526020600482015260036024820152624c4f4b60e81b604482015290519081900360640190fd5b6000805460ff60f01b1916815560408051608081018252338152600288810b602083015287900b918101919091528190819061260990606081016125fc6001600160801b038a16613f58565b600003600f0b9052613f69565b925092509250816000039450806000039350600085118061262a5750600084115b15612669576003830180546001600160801b038082168089018216600160801b93849004831689019092169092029091176001600160801b0319161790555b604080516001600160801b0388168152602081018790528082018690529051600289810b92908b900b9133917f0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c919081900360600190a450506000805460ff60f01b1916600160f01b179055509094909350915050565b60008060006126ed612bf0565b6126f785856143a1565b600285810b810b60009081526005602052604080822087840b90930b825281206003830154600681900b9367010000000000000082046001600160a01b0316928492600160d81b810463ffffffff169284929091600160f81b900460ff168061275f57600080fd5b6003820154600681900b985067010000000000000081046001600160a01b03169650600160d81b810463ffffffff169450600160f81b900460ff16806127a457600080fd5b50506040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b810b6020840181905261ffff600160b81b8404811695850195909552600160c81b830485166060850152600160d81b8304909416608084015260ff600160e81b8304811660a0850152600160f01b909204909116151560c08301529093508e810b91900b1215905061284d575093909403965090039350900390506128d0565b8a60020b816020015160020b12156128c1576000612869612c27565b602083015160408401516004546060860151939450600093849361289f936008938893879392916001600160801b031690613389565b9a9003989098039b5050949096039290920396509091030392506128d0915050565b50949093039650039350900390505b9250925092565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015481565b60056020526000908152604090208054600182015460028301546003909301546001600160801b03831693600160801b909304600f0b9290600681900b9067010000000000000081046001600160a01b031690600160d81b810463ffffffff1690600160f81b900460ff1688565b6000546001600160a01b031615612a1e576040805162461bcd60e51b8152602060048201526002602482015261414960f01b604482015290519081900360640190fd5b6000612a29826136a5565b9050600080612a41612a39612c27565b60089061446a565b6040805160e0810182526001600160a01b038816808252600288810b6020808501829052600085870181905261ffff898116606088018190529089166080880181905260a08801839052600160c0909801979097528154600160f01b73ffffffffffffffffffffffffffffffffffffffff19909116871762ffffff60a01b1916600160a01b62ffffff9787900b9790971696909602959095177fffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffff16600160c81b9091021761ffff60d81b1916600160d81b909602959095177fff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1692909217909355835191825281019190915281519395509193507f98636036cb66a9c19a37435efc1e90142190214e8abeb821bdba3f2990dd4c9592918290030190a150505050565b60008082600281900b620d89e71981612b9957fe5b05029050600083600281900b620d89e881612bb057fe5b0502905060008460020b83830360020b81612bc757fe5b0560010190508062ffffff166001600160801b03801681612be457fe5b0493505050505b919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612c2557600080fd5b565b4290565b60008060008460020b8660020b81612c3f57fe5b05905060008660020b128015612c6657508460020b8660020b81612c5f57fe5b0760020b15155b15612c7057600019015b8315612ce557600080612c82836144b6565b600182810b810b600090815260208d9052604090205460ff83169190911b80016000190190811680151597509294509092509085612cc757888360ff16860302612cda565b88612cd1826144c8565b840360ff168603025b965050505050612d63565b600080612cf4836001016144b6565b91509150600060018260ff166001901b031990506000818b60008660010b60010b8152602001908152602001600020541690508060001415955085612d4657888360ff0360ff16866001010102612d5c565b8883612d5183614568565b0360ff168660010101025b9650505050505b5094509492505050565b60008060008360020b12612d84578260020b612d8c565b8260020b6000035b9050620d89e8811115612dca576040805162461bcd60e51b81526020600482015260016024820152601560fa1b604482015290519081900360640190fd5b600060018216612dde57600160801b612df0565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615612e24576ffff97272373d413259a46990580e213a0260801c5b6004821615612e43576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615612e62576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615612e81576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615612ea0576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615612ebf576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615612ede576ffe5dee046a99a2a811c461f1969c30530260801c5b610100821615612efe576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b610200821615612f1e576ff987a7253ac413176f2b074cf7815e540260801c5b610400821615612f3e576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615612f5e576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615612f7e576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615612f9e576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615612fbe576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615612fde576f31be135f97d08fd981231505542fcfa60260801c5b62010000821615612fff576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b6202000082161561301f576e5d6af8dedb81196699c329225ee6040260801c5b6204000082161561303e576d2216e584f5fa1ea926041bedfe980260801c5b6208000082161561305b576b048a170391f7dc42444e8fa20260801c5b60008460020b131561307657806000198161307257fe5b0490505b64010000000081061561308a57600161308d565b60005b60ff16602082901c0192505050919050565b60008080806001600160a01b03808916908a1610158187128015906131245760006130d88989620f42400362ffffff16620f42406132d9565b9050826130f1576130ec8c8c8c6001614652565b6130fe565b6130fe8b8d8c60016146cd565b955085811061310f578a965061311e565b61311b8c8b838661478a565b96505b5061316e565b8161313b576131368b8b8b60006146cd565b613148565b6131488a8c8b6000614652565b935083886000031061315c5789955061316e565b61316b8b8a8a600003856147d6565b95505b6001600160a01b038a81169087161482156131d15780801561318d5750815b6131a35761319e878d8c60016146cd565b6131a5565b855b95508080156131b2575081155b6131c8576131c3878d8c6000614652565b6131ca565b845b945061321b565b8080156131db5750815b6131f1576131ec8c888c6001614652565b6131f3565b855b9550808015613200575081155b613216576132118c888c60006146cd565b613218565b845b94505b8115801561322b57508860000385115b15613237578860000394505b81801561325657508a6001600160a01b0316876001600160a01b031614155b15613265578589039350613282565b61327f868962ffffff168a620f42400362ffffff166141a9565b93505b50505095509550955095915050565b6000600160ff1b82106132a357600080fd5b5090565b808203828113156000831215146132bd57600080fd5b92915050565b818101828112156000831215146132bd57600080fd5b600080806000198587098686029250828110908390030390508061330f576000841161330457600080fd5b508290049050613382565b80841161331b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150505b9392505050565b60008063ffffffff8716613430576000898661ffff1661ffff81106133aa57fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff16151560608301529092508a161461341c57613419818a8988614822565b90505b806020015181604001519250925050613510565b8688036000806134458c8c858c8c8c8c6148d2565b91509150816000015163ffffffff168363ffffffff161415613477578160200151826040015194509450505050613510565b805163ffffffff8481169116141561349f578060200151816040015194509450505050613510565b8151815160208085015190840151918390039286039163ffffffff80841692908516910360060b816134cd57fe5b05028460200151018263ffffffff168263ffffffff1686604001518660400151036001600160a01b031602816134ff57fe5b048560400151019650965050505050505b97509795505050505050565b600295860b860b60009081526020979097526040909620600181018054909503909455938301805490920390915560038201805463ffffffff600160d81b6001600160a01b036701000000000000008085048216909603169094027fffffffffff0000000000000000000000000000000000000000ffffffffffffff90921691909117600681810b90960390950b66ffffffffffffff1666ffffffffffffff199095169490941782810485169095039093160263ffffffff60d81b1990931692909217905554600160801b9004600f0b90565b60008082600f0b121561365457826001600160801b03168260000384039150816001600160801b03161061364f576040805162461bcd60e51b81526020600482015260026024820152614c5360f01b604482015290519081900360640190fd5b6132bd565b826001600160801b03168284019150816001600160801b031610156132bd576040805162461bcd60e51b81526020600482015260026024820152614c4160f01b604482015290519081900360640190fd5b60006401000276a36001600160a01b038316108015906136e1575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b613716576040805162461bcd60e51b81526020600482015260016024820152602960f91b604482015290519081900360640190fd5b77ffffffffffffffffffffffffffffffffffffffff00000000602083901b166001600160801b03811160071b81811c67ffffffffffffffff811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c979088119617909417909217179091171717608081106137b757607f810383901c91506137c1565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b146139c257886001600160a01b03166139a682612d6d565b6001600160a01b031611156139bb57816139bd565b805b6139c4565b815b9998505050505050505050565b6000806000898961ffff1661ffff81106139e757fe5b60408051608081018252919092015463ffffffff8082168084526401000000008304600690810b810b900b6020850152600160581b83046001600160a01b031694840194909452600160f81b90910460ff161515606083015290925089161415613a575788859250925050613510565b8461ffff168461ffff16118015613a7857506001850361ffff168961ffff16145b15613a8557839150613a89565b8491505b8161ffff168960010161ffff1681613a9d57fe5b069250613aac81898989614822565b8a8461ffff1661ffff8110613abd57fe5b825191018054602084015160408501516060909501511515600160f81b027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001600160a01b03909616600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff60069390930b66ffffffffffffff16640100000000026affffffffffffff000000001963ffffffff90971663ffffffff199095169490941795909516929092171692909217929092161790555097509795505050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1781529251825160009485949389169392918291908083835b60208310613c025780518252601f199092019160209182019101613be3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613c64576040519150601f19603f3d011682016040523d82523d6000602084013e613c69565b606091505b5091509150818015613c97575080511580613c975750808060200190516020811015613c9457600080fd5b50515b613ccd576040805162461bcd60e51b81526020600482015260026024820152612a2360f11b604482015290519081900360640190fd5b5050505050565b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693919290918291908083835b60208310613d6d5780518252601f199092019160209182019101613d4e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613dcd576040519150601f19603f3d011682016040523d82523d6000602084013e613dd2565b606091505b5091509150818015613de657506020815110155b613def57600080fd5b808060200190516020811015613e0457600080fd5b50519250505090565b808201828110156132bd57600080fd5b604080513060248083019190915282518083039091018152604490910182526020810180516001600160e01b03166370a0823160e01b17815291518151600093849384936001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016939192909182919080838360208310613d6d5780518252601f199092019160209182019101613d4e565b6000808361ffff1611613ef3576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b8261ffff168261ffff1611613f09575081613382565b825b8261ffff168161ffff161015613f4f576001858261ffff1661ffff8110613f2e57fe5b01805463ffffffff191663ffffffff92909216919091179055600101613f0b565b50909392505050565b80600f81900b8114612beb57600080fd5b6000806000613f76612bf0565b613f88846020015185604001516143a1565b6040805160e0810182526000546001600160a01b0381168252600160a01b8104600290810b810b900b602080840182905261ffff600160b81b8404811685870152600160c81b84048116606080870191909152600160d81b8504909116608086015260ff600160e81b8504811660a0870152600160f01b909404909316151560c08501528851908901519489015192890151939461402c9491939092909190614acf565b93508460600151600f0b6000146141a157846020015160020b816020015160020b12156140815761407a6140638660200151612d6d565b6140708760400151612d6d565b8760600151614c84565b92506141a1565b846040015160020b816020015160020b12156141775760045460408201516001600160801b03909116906140d3906140b7612c27565b60208501516060860151608087015160089493929187916139d1565b6000805461ffff60c81b1916600160c81b61ffff938416021761ffff60b81b1916600160b81b939092169290920217905581516040870151614123919061411990612d6d565b8860600151614c84565b93506141416141358760200151612d6d565b83516060890151614cc8565b92506141518187606001516135ef565b600480546001600160801b0319166001600160801b0392909216919091179055506141a1565b61419e6141878660200151612d6d565b6141948760400151612d6d565b8760600151614cc8565b91505b509193909250565b60006141b68484846132d9565b9050600082806141c257fe5b84860911156133825760001981106141d957600080fd5b6001019392505050565b6040805160609490941b6bffffffffffffffffffffffff1916602080860191909152600293840b60e890811b60348701529290930b90911b60378401528051808403601a018152603a90930181528251928201929092206000908152929052902090565b60608060008361ffff1611614287576040805162461bcd60e51b81526020600482015260016024820152604960f81b604482015290519081900360640190fd5b865167ffffffffffffffff8111801561429f57600080fd5b506040519080825280602002602001820160405280156142c9578160200160208202803683370190505b509150865167ffffffffffffffff811180156142e457600080fd5b5060405190808252806020026020018201604052801561430e578160200160208202803683370190505b50905060005b87518110156143945761433f8a8a8a848151811061432e57fe5b60200260200101518a8a8a8a613389565b84838151811061434b57fe5b6020026020010184848151811061435e57fe5b60200260200101826001600160a01b03166001600160a01b03168152508260060b60060b81525050508080600101915050614314565b5097509795505050505050565b8060020b8260020b126143e1576040805162461bcd60e51b8152602060048201526003602482015262544c5560e81b604482015290519081900360640190fd5b620d89e719600283900b1215614424576040805162461bcd60e51b8152602060048201526003602482015262544c4d60e81b604482015290519081900360640190fd5b620d89e8600282900b1315614466576040805162461bcd60e51b815260206004820152600360248201526254554d60e81b604482015290519081900360640190fd5b5050565b6040805160808101825263ffffffff9283168082526000602083018190529282019290925260016060909101819052835463ffffffff1916909117909116600160f81b17909155908190565b60020b600881901d9161010090910790565b60008082116144d657600080fd5b600160801b82106144e957608091821c91015b68010000000000000000821061450157604091821c91015b640100000000821061451557602091821c91015b62010000821061452757601091821c91015b610100821061453857600891821c91015b6010821061454857600491821c91015b6004821061455857600291821c91015b60028210612beb57600101919050565b600080821161457657600080fd5b5060ff6001600160801b0382161561459157607f1901614599565b608082901c91505b67ffffffffffffffff8216156145b257603f19016145ba565b604082901c91505b63ffffffff8216156145cf57601f19016145d7565b602082901c91505b61ffff8216156145ea57600f19016145f2565b601082901c91505b60ff821615614604576007190161460c565b600882901c91505b600f82161561461e5760031901614626565b600482901c91505b60038216156146385760011901614640565b600282901c91505b6001821615612beb5760001901919050565b6000836001600160a01b0316856001600160a01b03161115614672579293925b8161469f5761469a836001600160801b03168686036001600160a01b0316600160601b6132d9565b6146c2565b6146c2836001600160801b03168686036001600160a01b0316600160601b6141a9565b90505b949350505050565b6000836001600160a01b0316856001600160a01b031611156146ed579293925b7bffffffffffffffffffffffffffffffff000000000000000000000000606084901b166001600160a01b03868603811690871661472957600080fd5b8361475957866001600160a01b031661474c8383896001600160a01b03166132d9565b8161475357fe5b0461477f565b61477f6147708383896001600160a01b03166141a9565b886001600160a01b0316614cf7565b979650505050505050565b600080856001600160a01b0316116147a157600080fd5b6000846001600160801b0316116147b757600080fd5b816147c95761469a8585856001614d02565b6146c28585856001614de3565b600080856001600160a01b0316116147ed57600080fd5b6000846001600160801b03161161480357600080fd5b816148155761469a8585856000614de3565b6146c28585856000614d02565b61482a61564a565b600085600001518503905060405180608001604052808663ffffffff1681526020018263ffffffff168660020b0288602001510160060b81526020016000856001600160801b03161161487e576001614880565b845b6001600160801b031673ffffffff00000000000000000000000000000000608085901b16816148ab57fe5b048860400151016001600160a01b0316815260200160011515815250915050949350505050565b6148da61564a565b6148e261564a565b888561ffff1661ffff81106148f357fe5b60408051608081018252919092015463ffffffff81168083526401000000008204600690810b810b900b6020840152600160581b82046001600160a01b031693830193909352600160f81b900460ff1615156060820152925061495890899089614ed8565b15614990578663ffffffff16826000015163ffffffff16141561497a57613510565b8161498783898988614822565b91509150613510565b888361ffff168660010161ffff16816149a557fe5b0661ffff1661ffff81106149b557fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b90910416151560608201819052909250614a6c57604080516080810182528a5463ffffffff811682526401000000008104600690810b810b900b6020830152600160581b81046001600160a01b031692820192909252600160f81b90910460ff161515606082015291505b614a7b88836000015189614ed8565b614ab2576040805162461bcd60e51b815260206004820152600360248201526213d31160ea1b604482015290519081900360640190fd5b614abf8989898887614f9b565b9150915097509795505050505050565b6000614ade60078787876141e3565b60015460025491925090600080600f87900b15614c24576000614aff612c27565b6000805460045492935090918291614b499160089186918591600160a01b810460020b9161ffff600160b81b83048116926001600160801b0390921691600160c81b900416613389565b9092509050614b8360058d8b8d8b8b87898b60007f000000000000000000000000000000000000000000000000000000000000000061513b565b9450614bba60058c8b8d8b8b87898b60017f000000000000000000000000000000000000000000000000000000000000000061513b565b93508415614bee57614bee60068d7f0000000000000000000000000000000000000000000000000000000000000000615325565b8315614c2057614c2060068c7f0000000000000000000000000000000000000000000000000000000000000000615325565b5050505b600080614c3660058c8c8b8a8a61538b565b9092509050614c47878a8484615437565b600089600f0b1215614c75578315614c6457614c6460058c6155cc565b8215614c7557614c7560058b6155cc565b50505050505095945050505050565b60008082600f0b12614caa57614ca5614ca085858560016146cd565b613291565b6146c5565b614cbd614ca085858560000360006146cd565b600003949350505050565b60008082600f0b12614ce457614ca5614ca08585856001614652565b614cbd614ca08585856000036000614652565b808204910615150190565b60008115614d755760006001600160a01b03841115614d3857614d3384600160601b876001600160801b03166132d9565b614d50565b6001600160801b038516606085901b81614d4e57fe5b045b9050614d6d614d686001600160a01b03881683613e0d565b6155f8565b9150506146c5565b60006001600160a01b03841115614da357614d9e84600160601b876001600160801b03166141a9565b614dba565b614dba606085901b6001600160801b038716614cf7565b905080866001600160a01b031611614dd157600080fd5b6001600160a01b0386160390506146c5565b600082614df15750836146c5565b7bffffffffffffffffffffffffffffffff000000000000000000000000606085901b168215614e91576001600160a01b03861684810290858281614e3157fe5b041415614e6257818101828110614e6057614e5683896001600160a01b0316836141a9565b93505050506146c5565b505b614e8882614e83878a6001600160a01b03168681614e7c57fe5b0490613e0d565b614cf7565b925050506146c5565b6001600160a01b03861684810290858281614ea857fe5b04148015614eb557508082115b614ebe57600080fd5b808203614e56614d68846001600160a01b038b16846141a9565b60008363ffffffff168363ffffffff1611158015614f0257508363ffffffff168263ffffffff1611155b15614f1e578163ffffffff168363ffffffff1611159050613382565b60008463ffffffff168463ffffffff1611614f46578363ffffffff1664010000000001614f4e565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611614f7f578363ffffffff1664010000000001614f87565b8363ffffffff165b64ffffffffff169091111595945050505050565b614fa361564a565b614fab61564a565b60008361ffff168560010161ffff1681614fc157fe5b0661ffff169050600060018561ffff16830103905060005b506002818301048961ffff87168281614fee57fe5b0661ffff8110614ffa57fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b9091041615156060820181905290955061506557806001019250614fd9565b898661ffff16826001018161507657fe5b0661ffff811061508257fe5b60408051608081018252929091015463ffffffff811683526401000000008104600690810b810b900b60208401526001600160a01b03600160581b8204169183019190915260ff600160f81b909104161515606082015285519094506000906150ed908b908b614ed8565b905080801561510657506151068a8a8760000151614ed8565b15615111575061512e565b8061512157600182039250615128565b8160010193505b50614fd9565b5050509550959350505050565b60028a810b900b600090815260208c90526040812080546001600160801b031682615166828d6135ef565b9050846001600160801b0316816001600160801b031611156151b4576040805162461bcd60e51b81526020600482015260026024820152614c4f60f01b604482015290519081900360640190fd5b6001600160801b03828116159082161581141594501561528a578c60020b8e60020b1361525a57600183018b9055600283018a90556003830180547fffffffffff0000000000000000000000000000000000000000ffffffffffffff166701000000000000006001600160a01b038c16021766ffffffffffffff191666ffffffffffffff60068b900b161763ffffffff60d81b1916600160d81b63ffffffff8a16021790555b6003830180547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f81b1790555b82546001600160801b0319166001600160801b038216178355856152d35782546152ce906152c990600160801b9004600f90810b810b908f900b6132c3565b613f58565b6152f4565b82546152f4906152c990600160801b9004600f90810b810b908f900b6132a7565b8354600f9190910b6001600160801b03908116600160801b0291161790925550909c9b505050505050505050505050565b8060020b8260020b8161533457fe5b0760020b1561534257600080fd5b60008061535d8360020b8560020b8161535757fe5b056144b6565b600191820b820b60009081526020979097526040909620805460ff9097169190911b90951890945550505050565b600285810b80820b60009081526020899052604080822088850b850b83529082209193849391929184918291908a900b126153d1575050600182015460028301546153e4565b8360010154880391508360020154870390505b6000808b60020b8b60020b121561540657505060018301546002840154615419565b84600101548a0391508460020154890390505b92909803979097039b96909503949094039850939650505050505050565b6040805160a08101825285546001600160801b0390811682526001870154602083015260028701549282019290925260038601548083166060830152600160801b900490911660808201526000600f85900b6154d65781516001600160801b03166154ce576040805162461bcd60e51b815260206004820152600260248201526104e560f41b604482015290519081900360640190fd5b5080516154e5565b81516154e290866135ef565b90505b60006155098360200151860384600001516001600160801b0316600160801b6132d9565b9050600061552f8460400151860385600001516001600160801b0316600160801b6132d9565b905086600f0b6000146155565787546001600160801b0319166001600160801b0384161788555b60018801869055600288018590556001600160801b03821615158061558457506000816001600160801b0316115b156155c2576003880180546001600160801b031981166001600160801b039182168501821617808216600160801b9182900483168501909216021790555b5050505050505050565b600290810b810b6000908152602092909252604082208281556001810183905590810182905560030155565b806001600160a01b0381168114612beb57600080fd5b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b6040805160808101825260008082526020820181905291810182905260608101919091529056fea164736f6c6343000706000aa164736f6c6343000706000ac66a3fdf07232cdd185febcc6579d408c241b47ae2f9907d84be655141eeaecc8203e88080cf62173156e680affd1d060607f098cea0d5527eda4cc31fce171636f568724129a76a7bee39b667515054a9779cc597a641e5cc63ebe155eaec0dfb1647e35d1cf86a09843b9aca0082baa29405aa229aec102f78ce0e852a812a388f076aa55580b8448a7c195f000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000018203e88080d94d6e295674b3997cd6f89033fb92b3531242ea4f3e3fb6279380dc2f5cb0345340413a169ee4ab87ade628921588f9351aaf7fa6cdefe6d0d6efd835d159b21bf9059b09843b9aca0083055ed68080b90587608060405234801561001057600080fd5b50610567806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630f28c97d146100465780631749e1e3146100645780634d2301cc14610085575b600080fd5b61004e610098565b60405161005b919061041f565b60405180910390f35b6100776100723660046102a7565b61009c565b60405161005b929190610428565b61004e610093366004610286565b610220565b4290565b8051439060609067ffffffffffffffff811180156100b957600080fd5b506040519080825280602002602001820160405280156100f357816020015b6100e061023a565b8152602001906001900390816100d85790505b50905060005b835181101561021a57600080600086848151811061011357fe5b60200260200101516000015187858151811061012b57fe5b60200260200101516020015188868151811061014357fe5b60200260200101516040015192509250925060005a90506000808573ffffffffffffffffffffffffffffffffffffffff1685856040516101839190610403565b60006040518083038160008787f1925050503d80600081146101c1576040519150601f19603f3d011682016040523d82523d6000602084013e6101c6565b606091505b509150915060005a8403905060405180606001604052808415158152602001828152602001838152508989815181106101fb57fe5b60200260200101819052505050505050505080806001019150506100f9565b50915091565b73ffffffffffffffffffffffffffffffffffffffff163190565b604051806060016040528060001515815260200160008152602001606081525090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461028157600080fd5b919050565b600060208284031215610297578081fd5b6102a08261025d565b9392505050565b600060208083850312156102b9578182fd5b823567ffffffffffffffff808211156102d0578384fd5b818501915085601f8301126102e3578384fd5b8135818111156102ef57fe5b6102fc8485830201610506565b81815284810190848601875b848110156103f457813587017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0606081838f03011215610346578a8bfd5b60408051606081018181108b8211171561035c57fe5b8252610369848d0161025d565b8152818401358c82015260608401358a811115610384578d8efd5b8085019450508e603f850112610398578c8dfd5b8b8401358a8111156103a657fe5b6103b68d85601f84011601610506565b93508084528f838287010111156103cb578d8efd5b808386018e86013783018c018d9052908101919091528552509287019290870190600101610308565b50909998505050505050505050565b6000825161041581846020870161052a565b9190910192915050565b90815260200190565b600060408083018584526020828186015281865180845260609350838701915083838202880101838901875b838110156104f6578983037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa001855281518051151584528681015187850152880151888401889052805188850181905260806104b582828801858c0161052a565b96880196601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01694909401909301925090850190600101610454565b50909a9950505050505050505050565b60405181810167ffffffffffffffff8111828210171561052257fe5b604052919050565b60005b8381101561054557818101518382015260200161052d565b83811115610554576000848401525b5050505056fea164736f6c6343000706000a8203e880809df142f081a14e08cb93dfd5849845c79865c3c5b5278f4c8ce3e98d91ac66a66baa1bbf2f18cb242a815219c97d394b0834a699a92b8cad99a508bc19b8133d1b", "globalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "batchNum": 3, - "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "oldBatchNum": 2, + "oldAccInputhHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldStateRoot": "0x5b6ce18bff9163a1ddb4becbd8d140d59b5efa3ed30a481cb00b974c21bdf48b", "sequencerAddr": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "timestamp": 1661520590 diff --git a/tools/genesis/generator.go b/tools/genesis/generator.go deleted file mode 100644 index 7680278d82..0000000000 --- a/tools/genesis/generator.go +++ /dev/null @@ -1,199 +0,0 @@ -package main - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "math/big" - "os/exec" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/0xPolygonHermez/zkevm-node/tools/genesis/genesisparser" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/go-git/go-git/v5/storage/memory" -) - -const ( - repoURL = "https://github.com/0xPolygonHermez/zkevm-contracts" - inputFile = "deployment/deployment_v2-0/genesis.json" - outputFile = "../../config/genesis.go" -) - -// genesisAccountReader struct -type genesisAccountReader struct { - Balance string `json:"balance"` - Nonce string `json:"nonce"` - Address string `json:"address"` - Bytecode string `json:"bytecode"` - Storage map[string]string `json:"storage"` -} - -// genesisReader struct -type genesisReader struct { - Root string `json:"root"` - Accounts []genesisAccountReader `json:"genesis"` -} - -func (gr genesisReader) GenesisAccountTest() []genesisparser.GenesisAccountTest { - accs := []genesisparser.GenesisAccountTest{} - for i := 0; i < len(gr.Accounts); i++ { - accs = append(accs, genesisparser.GenesisAccountTest{ - Balance: gr.Accounts[i].Balance, - Nonce: gr.Accounts[i].Nonce, - Address: gr.Accounts[i].Address, - Bytecode: gr.Accounts[i].Bytecode, - Storage: gr.Accounts[i].Storage, - }) - } - return accs -} - -func main() { - rawGenesis := getLatestGenesisRaw() - actions := genesisparser.GenesisTest2Actions(rawGenesis.GenesisAccountTest()) - genGoCode(actions) - err := assertGenesis(rawGenesis.Root) - if err != nil { - panic(err) - } -} - -func getLatestGenesisRaw() genesisReader { - fs := memfs.New() - - _, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{ - ReferenceName: plumbing.NewBranchReferenceName("main"), - URL: repoURL, - }) - if err != nil { - panic(fmt.Errorf("error when clone repo: %v", err)) - } - - file, err := fs.Open(inputFile) - if err != nil { - panic(fmt.Errorf("error when open file: %v", err)) - } - - scanner := bufio.NewScanner(file) - - genesis := make([]byte, 0) - - for scanner.Scan() { - genesis = append(genesis, scanner.Bytes()...) - } - var genesisData genesisReader - err = json.Unmarshal(genesis, &genesisData) - if err != nil { - panic(fmt.Errorf("error json unmarshal: %v", err)) - } - return genesisData -} - -func genGoCode(actions []*state.GenesisAction) { - gJson, _ := json.MarshalIndent(actions, "", " ") - gString := string(gJson) - gString = strings.Replace(gString, "[\n", "", -1) - gString = strings.Replace(gString, "]", "", -1) - gString = `package config - -import ( - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/state" -) - -var commonGenesisActions = []*state.GenesisAction{ -` + gString + ` -}` - - gString = strings.Replace(gString, `"address"`, "Address", -1) - gString = strings.Replace(gString, `"type"`, "Type", -1) - gString = strings.Replace(gString, `"storagePosition"`, "StoragePosition", -1) - gString = strings.Replace(gString, `"value"`, "Value", -1) - gString = strings.Replace(gString, `"bytecode"`, "Bytecode", -1) - gString = strings.Replace(gString, `"key"`, "Key", -1) - gString = strings.Replace(gString, `"root"`, "Root", -1) - gString = strings.Replace(gString, "\"\n", "\",\n", -1) - gString = strings.Replace(gString, "}\n", "},\n", -1) - gString = strings.Replace(gString, "Type: 0,", "Type: int(merkletree.LeafTypeBalance),", -1) - gString = strings.Replace(gString, "Type: 1,", "Type: int(merkletree.LeafTypeNonce),", -1) - gString = strings.Replace(gString, "Type: 2,", "Type: int(merkletree.LeafTypeCode),", -1) - gString = strings.Replace(gString, "Type: 3,", "Type: int(merkletree.LeafTypeStorage),", -1) - - err := ioutil.WriteFile(outputFile, []byte(gString), 0600) //nolint:gomnd - if err != nil { - panic(fmt.Errorf("error writing file: %v", err)) - } - - // format code - cmd := exec.Command("gofmt", "-s", "-w", outputFile) - res, err := cmd.CombinedOutput() - if err != nil { - panic(fmt.Errorf("error formating file: %s.\n%w", string(res), err)) - } -} - -func assertGenesis(expectedRoot string) (err error) { - // Build node - if err = operations.RunMakeTarget("build-docker"); err != nil { - log.Error(err) - return - } - // Start DB and executor - if err = operations.RunMakeTarget("run-db"); err != nil { - log.Error(err) - return - } - if err = operations.RunMakeTarget("run-zkprover"); err != nil { - log.Error(err) - return - } - // Stop everything once done - defer func() { - if defErr := operations.Teardown(); defErr != nil { - err = fmt.Errorf("Error tearing down components: %s", defErr.Error()) - } - }() - - // Setup opsman - opsCfg := operations.GetDefaultOperationsConfig() - opsCfg.State.MaxCumulativeGasUsed = 80000000000 - opsman, err := operations.NewManager(context.Background(), opsCfg) - if err != nil { - log.Error(err) - return - } - - // Run node - err = opsman.Setup() - if err != nil { - log.Error(err) - return - } - - // Get Genesis root using jRPC - client, err := ethclient.Dial("http://localhost:8123") - if err != nil { - log.Error(err) - return - } - blockHeader, err := client.HeaderByNumber(context.Background(), big.NewInt(0)) - if err != nil { - log.Error(err) - return - } - actualRoot := "0x" + blockHeader.Root.Hex() - if actualRoot != expectedRoot { - err = fmt.Errorf("Root missmatch: expected: %s, actual %s", expectedRoot, actualRoot) - return - } - fmt.Printf("SUCCESS: expected: %s, actual %s\n", expectedRoot, actualRoot) - return -} diff --git a/tools/network/network.go b/tools/network/network.go index cbe07c2b0f..7bda076adc 100644 --- a/tools/network/network.go +++ b/tools/network/network.go @@ -64,7 +64,7 @@ package network // L1Deployer L1Deployer // // Sequencer address, comes from the keystore passed to node // // on config -// SequencerAddress, SequencerPrivateKey string +// sequencerAddress, SequencerPrivateKey string // TxTimeout time.Duration // } @@ -136,11 +136,11 @@ package network // return err // } -// sequencerAddress := common.HexToAddress(nc.SequencerAddress) +// sequencerAddress := common.HexToAddress(nc.sequencerAddress) // if nc.L1Deployer.L1ETHAmountToSequencer != "" { // // Send some Ether from L1 deployer to sequencer acc // ethAmount, _ := big.NewInt(0).SetString(nc.L1Deployer.L1ETHAmountToSequencer, encoding.Base10) -// log.Infof("Transferring %s L1 ETH to sequencer %q from L1 deployer %q", nc.L1Deployer.L1ETHAmountToSequencer, nc.SequencerAddress, nc.L1Deployer.Address) +// log.Infof("Transferring %s L1 ETH to sequencer %q from L1 deployer %q", nc.L1Deployer.L1ETHAmountToSequencer, nc.sequencerAddress, nc.L1Deployer.Address) // fromAddress := common.HexToAddress(nc.L1Deployer.Address) // nonce, err := clientL1.PendingNonceAt(ctx, fromAddress) // if err != nil { @@ -173,7 +173,7 @@ package network // } // // Send matic to sequencer // maticAmount, _ := big.NewInt(0).SetString(nc.L1Deployer.L1MaticAmountToSequencer, encoding.Base10) -// log.Infof("Transferring %s L1 MATIC tokens to sequencer %q from L1 deployer %q", nc.L1Deployer.L1MaticAmountToSequencer, nc.SequencerAddress, nc.L1Deployer.Address) +// log.Infof("Transferring %s L1 MATIC tokens to sequencer %q from L1 deployer %q", nc.L1Deployer.L1MaticAmountToSequencer, nc.sequencerAddress, nc.L1Deployer.Address) // tx, err := maticTokenSC.Transfer(authDeployer, sequencerAddress, maticAmount) // if err != nil { // return err @@ -186,7 +186,7 @@ package network // } // // approve tokens to be used by PoE SC on behalf of the sequencer -// log.Infof("Approving %s L1 MATIC tokens to be used by PoE on behalf of the sequencer %q", maticAmount.String(), nc.SequencerAddress) +// log.Infof("Approving %s L1 MATIC tokens to be used by PoE on behalf of the sequencer %q", maticAmount.String(), nc.sequencerAddress) // tx, err = maticTokenSC.Approve(authSequencer, cfg.NetworkConfig.PoEAddr, maticAmount) // if err != nil { // return err diff --git a/tools/rlp/main.go b/tools/rlp/main.go index f08f6d8a37..d4f00eca50 100644 --- a/tools/rlp/main.go +++ b/tools/rlp/main.go @@ -8,20 +8,16 @@ import ( "strings" "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/proofofefficiency" + "github.com/0xPolygonHermez/zkevm-node/etherman/smartcontracts/polygonzkevm" "github.com/0xPolygonHermez/zkevm-node/hex" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rlp" "github.com/urfave/cli/v2" ) -const ( - ether155V = 27 -) - func main() { app := cli.NewApp() app.Name = "RlpTool" @@ -75,7 +71,7 @@ func decode(ctx *cli.Context) error { log.Error("error decoding rawTxs: ", err) return err } - txs, err := decodeRawTxs(bytesRawTxs) + txs, _, err := state.DecodeTxs(bytesRawTxs) if err != nil { log.Error("error decoding tx callData: ", err) return err @@ -174,7 +170,6 @@ func encode(ctx *cli.Context) error { s, _ := new(big.Int).SetString(sS, encoding.Base10) log.Info("S: ", s) - var rawTxHex string var txLegacy = types.LegacyTx{ Nonce: nonce, GasPrice: gasPrice, @@ -188,40 +183,18 @@ func encode(ctx *cli.Context) error { } tx := types.NewTx(&txLegacy) - V, R, S := tx.RawSignatureValues() - sign := 1 - (V.Uint64() & 1) - - txCodedRlp, err := rlp.EncodeToBytes([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.ChainId(), uint(0), uint(0), - }) - if err != nil { - log.Error("error encoding rlp tx: ", err) - return fmt.Errorf("error encoding rlp tx: " + err.Error()) - } - newV := new(big.Int).Add(big.NewInt(ether155V), big.NewInt(int64(sign))) - newRPadded := fmt.Sprintf("%064s", R.Text(hex.Base)) - newSPadded := fmt.Sprintf("%064s", S.Text(hex.Base)) - newVPadded := fmt.Sprintf("%02s", newV.Text(hex.Base)) - rawTxHex = rawTxHex + hex.EncodeToString(txCodedRlp) + newRPadded + newSPadded + newVPadded - - rawTx, err := hex.DecodeString(rawTxHex) + rawBytes, err := state.EncodeTransactions([]types.Transaction{*tx}) if err != nil { - log.Error("error coverting hex string to []byte. Error: ", err) - return fmt.Errorf("error coverting hex string to []byte. Error: " + err.Error()) + log.Error("error encoding txs: ", err) + return err } - log.Info("encoded tx with signature using RLP in []byte: ", rawTx) - log.Info("rawtx with signature using RLP in hex: ", hex.EncodeToString(rawTx)) + log.Info("encoded tx with signature using RLP in []byte: ", rawBytes) + log.Info("rawtx with signature using RLP in hex: ", hex.EncodeToString(rawBytes)) return nil } -func printTxs(txs []*types.Transaction, rawTxs []byte) { +func printTxs(txs []types.Transaction, rawTxs []byte) { log.Info("RawTxs: ", hex.EncodeToHex(rawTxs)) for _, tx := range txs { log.Info("#######################################################################") @@ -244,7 +217,7 @@ func printTxs(txs []*types.Transaction, rawTxs []byte) { } } -func decodeFullCallDataToTxs(txsData []byte) ([]*types.Transaction, []byte, error) { +func decodeFullCallDataToTxs(txsData []byte) ([]types.Transaction, []byte, error) { // The first 4 bytes are the function hash bytes. These bytes has to be ripped. // After that, the unpack method is used to read the call data. // The txs data is a chunk of concatenated rawTx. This rawTx is the encoded tx information in rlp + the signature information (v, r, s). @@ -252,7 +225,7 @@ func decodeFullCallDataToTxs(txsData []byte) ([]*types.Transaction, []byte, erro // Extract coded txs. // Load contract ABI - abi, err := abi.JSON(strings.NewReader(proofofefficiency.ProofofefficiencyABI)) + abi, err := abi.JSON(strings.NewReader(polygonzkevm.PolygonzkevmABI)) if err != nil { log.Fatal("error reading smart contract abi: ", err) } @@ -271,74 +244,6 @@ func decodeFullCallDataToTxs(txsData []byte) ([]*types.Transaction, []byte, erro txsData = data[0].([]byte) - txs, err := decodeRawTxs(txsData) + txs, _, err := state.DecodeTxs(txsData) return txs, txsData, err } - -func decodeRawTxs(txsData []byte) ([]*types.Transaction, error) { - // Process coded txs - var pos int64 - var txs []*types.Transaction - const ( - headerByteLength = 2 - sLength = 32 - rLength = 32 - vLength = 1 - c0 = 192 // 192 is c0. This value is defined by the rlp protocol - ff = 255 // max value of rlp header - shortRlp = 55 // length of the short rlp codification - f7 = 247 // 192 + 55 = c0 + shortRlp - etherNewV = 35 - mul2 = 2 - ) - txDataLength := len(txsData) - for pos < int64(txDataLength) { - num, err := strconv.ParseInt(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, encoding.BitSize64) - if err != nil { - log.Error("error parsing header length: ", err) - return []*types.Transaction{}, err - } - // First byte is the length and must be ignored - len := num - c0 - 1 - - if len > shortRlp { // If rlp is bigger than length 55 - // numH is the length of the bytes that give the length of the rlp - numH, err := strconv.ParseInt(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, encoding.BitSize64) - if err != nil { - log.Error("error parsing length of the bytes: ", err) - return []*types.Transaction{}, err - } - // n is the length of the rlp data without the header (1 byte) for example "0xf7" - n, err := strconv.ParseInt(hex.EncodeToString(txsData[pos+1:pos+1+numH-f7]), hex.Base, encoding.BitSize64) // +1 is the header. For example 0xf7 - if err != nil { - log.Error("error parsing length: ", err) - return []*types.Transaction{}, err - } - len = n + 1 // +1 is the header. For example 0xf7 - } - - fullDataTx := txsData[pos : pos+len+rLength+sLength+vLength+headerByteLength] - txInfo := txsData[pos : pos+len+headerByteLength] - r := txsData[pos+len+headerByteLength : pos+len+rLength+headerByteLength] - s := txsData[pos+len+rLength+headerByteLength : pos+len+rLength+sLength+headerByteLength] - v := txsData[pos+len+rLength+sLength+headerByteLength : pos+len+rLength+sLength+vLength+headerByteLength] - - pos = pos + len + rLength + sLength + vLength + headerByteLength - - // Decode tx - var tx types.LegacyTx - err = rlp.DecodeBytes(txInfo, &tx) - if err != nil { - log.Error("error decoding tx bytes: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo)) - return []*types.Transaction{}, err - } - - //tx.V = v-27+chainId*2+35 - tx.V = new(big.Int).Add(new(big.Int).Sub(new(big.Int).SetBytes(v), big.NewInt(ether155V)), new(big.Int).Add(new(big.Int).Mul(tx.V, big.NewInt(mul2)), big.NewInt(etherNewV))) - tx.R = new(big.Int).SetBytes(r) - tx.S = new(big.Int).SetBytes(s) - - txs = append(txs, types.NewTx(&tx)) - } - return txs, nil -} diff --git a/tools/zkevmprovermock/Dockerfile b/tools/zkevmprovermock/Dockerfile index 574ffcd716..d4d21e0d8c 100644 --- a/tools/zkevmprovermock/Dockerfile +++ b/tools/zkevmprovermock/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17-alpine AS build +FROM golang:1.19-alpine AS build ENV CGO_ENABLED=0 WORKDIR /app diff --git a/tools/zkevmprovermock/cmd/client.go b/tools/zkevmprovermock/cmd/client.go deleted file mode 100644 index d9763f30b5..0000000000 --- a/tools/zkevmprovermock/cmd/client.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import ( - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/urfave/cli/v2" -) - -func runClient(cliCtx *cli.Context) error { - log.Info("Running zkEVM Prover Client mock...") - - return nil -} diff --git a/tools/zkevmprovermock/cmd/main.go b/tools/zkevmprovermock/cmd/main.go deleted file mode 100644 index f314242d85..0000000000 --- a/tools/zkevmprovermock/cmd/main.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/urfave/cli/v2" -) - -const ( - defaultStateDBPort = 50061 - defaultExecutorPort = 50071 - defaultTestVectorPath = "../../test/vectors/src/merkle-tree/" -) - -func main() { - app := cli.NewApp() - serverFlags := []cli.Flag{ - &cli.UintFlag{ - Name: "statedb-port", - Usage: "StateDB server port", - Required: false, - Value: defaultStateDBPort, - }, - &cli.UintFlag{ - Name: "executor-port", - Usage: "Executor server port", - Required: false, - Value: defaultExecutorPort, - }, - &cli.StringFlag{ - Name: "test-vector-path", - Usage: "Test vector path", - Required: false, - Value: defaultTestVectorPath, - }, - &cli.StringFlag{ - Name: "host", - Usage: "Server host", - Required: false, - Value: "0.0.0.0", - }, - } - clientFlags := []cli.Flag{ - &cli.StringFlag{ - Name: "state-db-serveruri", - Usage: "StateDB server URI", - Required: false, - Value: fmt.Sprintf("127.0.0.1:%d", defaultStateDBPort), - }, - &cli.StringFlag{ - Name: "executor-serveruri", - Usage: "Executor server URI", - Required: false, - Value: fmt.Sprintf("127.0.0.1:%d", defaultExecutorPort), - }, - } - app.Commands = []*cli.Command{ - { - Name: "server", - Usage: "Run zkEVM Prover mock server", - Action: runServer, - Flags: serverFlags, - }, - { - Name: "client", - Usage: "Run zkEVM Prover mock client", - Action: runClient, - Flags: clientFlags, - }, - } - err := app.Run(os.Args) - if err != nil { - log.Fatal(err) - } -} diff --git a/tools/zkevmprovermock/cmd/server.go b/tools/zkevmprovermock/cmd/server.go deleted file mode 100644 index f4fd60d6c6..0000000000 --- a/tools/zkevmprovermock/cmd/server.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/0xPolygonHermez/zkevm-node/log" - stateDBPpb "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" - executorPb "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/server" - "github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/testvector" - "github.com/spf13/afero" - "github.com/urfave/cli/v2" - "google.golang.org/grpc" -) - -func runServer(cliCtx *cli.Context) error { - log.Info("Running zkEVM Prover Server mock...") - - s := grpc.NewServer() - - aferoFs := afero.NewOsFs() - - tvContainer, err := testvector.NewContainer(cliCtx.String("test-vector-path"), aferoFs) - if err != nil { - log.Fatalf("Could not create test vector container: %v", err) - } - - stateDBAddress := fmt.Sprintf("%s:%d", cliCtx.String("host"), cliCtx.Uint("statedb-port")) - stateDBSrv := server.NewStateDBMock(stateDBAddress, tvContainer) - - stateDBPpb.RegisterStateDBServiceServer(s, stateDBSrv) - go stateDBSrv.Start() - - executorAddress := fmt.Sprintf("%s:%d", cliCtx.String("host"), cliCtx.Uint("executor-port")) - executorSrv := server.NewExecutorMock(executorAddress, tvContainer) - - executorPb.RegisterExecutorServiceServer(s, executorSrv) - go executorSrv.Start() - - operations.WaitSignal(func() { - stateDBSrv.Stop() - executorSrv.Stop() - }) - return nil -} diff --git a/tools/zkevmprovermock/server/executor.go b/tools/zkevmprovermock/server/executor.go deleted file mode 100644 index 31fd20dc77..0000000000 --- a/tools/zkevmprovermock/server/executor.go +++ /dev/null @@ -1,411 +0,0 @@ -package server - -import ( - "context" - "encoding/hex" - "fmt" - "math/big" - "net" - "strconv" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/state/runtime/executor/pb" - "github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/testvector" - "github.com/ethereum/go-ethereum/common" - "google.golang.org/grpc" -) - -const ( - bits64 = 64 - bits32 = 32 -) - -// ExecutorMock represents and Executor mock server -type ExecutorMock struct { - // address is the address on which the gRPC server will listen, eg. 0.0.0.0:50071 - address string - - tvContainer *testvector.Container - - // srv is an insance of the gRPC server. - srv *grpc.Server - - // embedding an instance of pb.UnimplementedExecutorServiceServer will allow us - // to implement all the required method interfaces. - pb.UnimplementedExecutorServiceServer -} - -// NewExecutorMock is the ExecutorMock constructor. -func NewExecutorMock(address string, tvContainer *testvector.Container) *ExecutorMock { - return &ExecutorMock{ - address: address, - tvContainer: tvContainer, - } -} - -// Start sets up the stateDB server to process requests. -func (server *ExecutorMock) Start() { - lis, err := net.Listen("tcp", server.address) - if err != nil { - log.Fatalf("failed to listen: %v", err) - } - - server.srv = grpc.NewServer() - pb.RegisterExecutorServiceServer(server.srv, server) - - log.Infof("Executor mock server: listening at %s", server.address) - if err := server.srv.Serve(lis); err != nil { - log.Fatalf("failed to serve: %v", err) - } -} - -// Stop stops the server. -func (server *ExecutorMock) Stop() { - log.Info("Executor mock server: stopping...") - server.srv.Stop() -} - -// ProcessBatch implements the ProcessBatch gRPC method. -func (server *ExecutorMock) ProcessBatch(ctx context.Context, request *pb.ProcessBatchRequest) (*pb.ProcessBatchResponse, error) { - processBatchResponse, err := server.tvContainer.FindProcessBatchResponse(hex.EncodeToString(request.BatchL2Data)) - if err != nil { - return nil, err - } - - cumulativeGasUSed, err := strconv.ParseUint(processBatchResponse.CumulativeGasUsed, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", processBatchResponse.CumulativeGasUsed, err) - } - - responses := []*pb.ProcessTransactionResponse{} - for _, response := range processBatchResponse.Responses { - newResponse, err := translateResponse(response) - if err != nil { - return nil, err - } - responses = append(responses, newResponse) - } - - if strings.HasPrefix(processBatchResponse.NewStateRoot, "0x") { // nolint - processBatchResponse.NewStateRoot = processBatchResponse.NewStateRoot[2:] - } - if strings.HasPrefix(processBatchResponse.NewLocalExitRoot, "0x") { // nolint - processBatchResponse.NewLocalExitRoot = processBatchResponse.NewLocalExitRoot[2:] - } - - return &pb.ProcessBatchResponse{ - CumulativeGasUsed: cumulativeGasUSed, - Responses: responses, - NewStateRoot: common.Hex2Bytes(processBatchResponse.NewStateRoot), - NewLocalExitRoot: common.Hex2Bytes(processBatchResponse.NewLocalExitRoot), - CntKeccakHashes: processBatchResponse.CntKeccakHashes, - CntPoseidonHashes: processBatchResponse.CntPoseidonHashes, - CntPoseidonPaddings: processBatchResponse.CntPoseidonPaddings, - CntMemAligns: processBatchResponse.CntMemAligns, - CntArithmetics: processBatchResponse.CntArithmetics, - CntBinaries: processBatchResponse.CntBinaries, - CntSteps: processBatchResponse.CntSteps, - }, nil -} - -func translateResponse(response *testvector.ProcessTransactionResponse) (*pb.ProcessTransactionResponse, error) { - var err error - - var gasLeft uint64 - if response.GasLeft != "" { - gasLeft, err = strconv.ParseUint(response.GasLeft, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", response.GasLeft, err) - } - } - - var gasUsed uint64 - if response.GasUsed != "" { - gasUsed, err = strconv.ParseUint(response.GasUsed, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", response.GasUsed, err) - } - } - - var gasRefunded uint64 - if response.GasRefunded != "" { - gasRefunded, err = strconv.ParseUint(response.GasRefunded, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", response.GasRefunded, err) - } - } - - logs, err := translateLogs(response.Logs) - if err != nil { - return nil, err - } - - callTrace, err := translateCallTrace(response.CallTrace) - if err != nil { - return nil, err - } - - if strings.HasPrefix(response.TxHash, "0x") { // nolint - response.TxHash = response.TxHash[2:] - } - if strings.HasPrefix(response.StateRoot, "0x") { // nolint - response.StateRoot = response.StateRoot[2:] - } - - return &pb.ProcessTransactionResponse{ - TxHash: common.Hex2Bytes(response.TxHash), - Type: response.Type, - GasLeft: gasLeft, - GasUsed: gasUsed, - GasRefunded: gasRefunded, - StateRoot: common.Hex2Bytes(response.StateRoot), - Logs: logs, - CallTrace: callTrace, - }, nil -} - -func translateLogs(inputLogs []*testvector.Log) ([]*pb.Log, error) { - logs := []*pb.Log{} - - for _, log := range inputLogs { - topics := [][]byte{} - - for _, topic := range log.Topics { - newTopic, err := hex.DecodeString(topic) - if err != nil { - return nil, err - } - topics = append(topics, newTopic) - } - - data := []byte{} - var err error - if len(log.Data) > 0 { - data, err = hex.DecodeString(log.Data[0]) - if err != nil { - return nil, err - } - } - - if strings.HasPrefix(log.TxHash, "0x") { // nolint - log.TxHash = log.TxHash[2:] - } - if strings.HasPrefix(log.BatchHash, "0x") { // nolint - log.BatchHash = log.BatchHash[2:] - } - - newLog := &pb.Log{ - Address: log.Address, - Topics: topics, - Data: data, - BatchNumber: log.BatchNumber, - TxHash: common.Hex2Bytes(log.TxHash), - TxIndex: log.TxIndex, - BatchHash: common.Hex2Bytes(log.BatchHash), - Index: log.Index, - } - - logs = append(logs, newLog) - } - return logs, nil -} - -func translateCallTrace(callTrace *testvector.CallTrace) (*pb.CallTrace, error) { - ctx, err := translateTransactionContext(callTrace.Context) - if err != nil { - return nil, err - } - - steps, err := translateTransactionSteps(callTrace.Steps) - if err != nil { - return nil, err - } - - return &pb.CallTrace{ - Context: ctx, - Steps: steps, - }, nil -} - -func translateTransactionContext(ctx *testvector.TransactionContext) (*pb.TransactionContext, error) { - var err error - var gas uint64 - if ctx.Gas != "" { - gas, err = strconv.ParseUint(ctx.Gas, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", ctx.Gas, err) - } - } - var value uint64 - if ctx.Value != "" { - value, err = strconv.ParseUint(ctx.Value, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", ctx.Value, err) - } - } - - var gasUsed uint64 - if ctx.GasUsed != "" { - gasUsed, err = strconv.ParseUint(ctx.GasUsed, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", ctx.GasUsed, err) - } - } - - var gasPrice uint64 - if ctx.GasPrice != "" { - gasPrice, err = strconv.ParseUint(ctx.GasPrice, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", ctx.GasPrice, err) - } - } - - var executionTime uint64 - if ctx.ExecutionTime != "" { - executionTime, err = strconv.ParseUint(ctx.ExecutionTime, encoding.Base10, bits32) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint32: %v", ctx.ExecutionTime, err) - } - } - if strings.HasPrefix(ctx.Data, "0x") { // nolint - ctx.Data = ctx.Data[2:] - } - if strings.HasPrefix(ctx.Batch, "0x") { // nolint - ctx.Batch = ctx.Batch[2:] - } - if strings.HasPrefix(ctx.Output, "0x") { // nolint - ctx.Output = ctx.Output[2:] - } - if strings.HasPrefix(ctx.OldStateRoot, "0x") { // nolint - ctx.OldStateRoot = ctx.OldStateRoot[2:] - } - - return &pb.TransactionContext{ - Type: ctx.Type, - From: ctx.From, - To: ctx.To, - Data: common.Hex2Bytes(ctx.Data), - Gas: gas, - Value: new(big.Int).SetUint64(value).String(), - GasUsed: gasUsed, - Batch: common.Hex2Bytes(ctx.Batch), - Output: common.Hex2Bytes(ctx.Output), - GasPrice: new(big.Int).SetUint64(gasPrice).String(), - ExecutionTime: uint32(executionTime), - OldStateRoot: common.Hex2Bytes(ctx.OldStateRoot), - }, nil -} - -func translateTransactionSteps(inputSteps []*testvector.TransactionStep) ([]*pb.TransactionStep, error) { - steps := []*pb.TransactionStep{} - - for _, inputStep := range inputSteps { - contract, err := translateContract(inputStep.Contract) - if err != nil { - return nil, err - } - - var gas uint64 - if inputStep.RemainingGas != "" { - gas, err = strconv.ParseUint(inputStep.RemainingGas, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", inputStep.RemainingGas, err) - } - } - var gasCost uint64 - if inputStep.GasCost != "" { - gasCost, err = strconv.ParseUint(inputStep.GasCost, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", inputStep.GasCost, err) - } - } - var gasRefund uint64 - if inputStep.GasRefund != "" { - gasRefund, err = strconv.ParseUint(inputStep.GasRefund, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", inputStep.GasRefund, err) - } - } - var op uint64 - if inputStep.Op != "" { - if strings.HasPrefix(inputStep.Op, "0x") { // nolint - inputStep.Op = inputStep.Op[2:] - } - opBI, ok := new(big.Int).SetString(inputStep.Op, encoding.Base16) - if !ok { - return nil, fmt.Errorf("Could not convert base16 %q to big int", inputStep.Op) - } - op = opBI.Uint64() - } - var pbErr uint64 - if inputStep.Error != "" { - pbErr, err = strconv.ParseUint(inputStep.Error, encoding.Base10, bits32) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint32: %v", inputStep.Error, err) - } - } - - if strings.HasPrefix(inputStep.StateRoot, "0x") { // nolint - inputStep.StateRoot = inputStep.StateRoot[2:] - } - - memory := []byte{} - if len(inputStep.Memory) > 0 { - memory = common.Hex2Bytes(inputStep.Memory[0]) - } - returnData := []byte{} - if len(inputStep.ReturnData) > 0 { - returnData = common.Hex2Bytes(inputStep.ReturnData[0]) - } - - newStep := &pb.TransactionStep{ - StateRoot: common.Hex2Bytes(inputStep.StateRoot), - Depth: inputStep.Depth, - Pc: inputStep.Pc, - Gas: gas, - GasCost: gasCost, - GasRefund: gasRefund, - Op: uint32(op), - Stack: inputStep.Stack, - Memory: memory, - ReturnData: returnData, - Contract: contract, - Error: pb.Error(pbErr), - } - steps = append(steps, newStep) - } - - return steps, nil -} - -func translateContract(contract *testvector.Contract) (*pb.Contract, error) { - var err error - var value uint64 - if contract.Value != "" { - value, err = strconv.ParseUint(contract.Value, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", contract.Value, err) - } - } - var gas uint64 - if contract.Gas != "" { - gas, err = strconv.ParseUint(contract.Gas, encoding.Base10, bits64) - if err != nil { - return nil, fmt.Errorf("Could not convert %q to uint64: %v", contract.Gas, err) - } - } - - if strings.HasPrefix(contract.Data, "0x") { // nolint - contract.Data = contract.Data[2:] - } - - return &pb.Contract{ - Address: contract.Address, - Caller: contract.Caller, - Data: common.Hex2Bytes(contract.Data), - Value: new(big.Int).SetUint64(value).String(), - Gas: gas, - }, nil -} diff --git a/tools/zkevmprovermock/server/statedb.go b/tools/zkevmprovermock/server/statedb.go deleted file mode 100644 index fa967ea650..0000000000 --- a/tools/zkevmprovermock/server/statedb.go +++ /dev/null @@ -1,158 +0,0 @@ -package server - -import ( - "context" - "fmt" - "math/big" - "net" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/hex" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/merkletree" - "github.com/0xPolygonHermez/zkevm-node/merkletree/pb" - "github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/testvector" - "google.golang.org/grpc" -) - -// StateDBMock represents a StateDB mock server. -type StateDBMock struct { - // address is the address on which the gRPC server will listen, eg. 0.0.0.0:50061 - address string - - tvContainer *testvector.Container - - // srv is an insance of the gRPC server. - srv *grpc.Server - // embedding an instance of pb.UnimplementedStateDBServiceServer will allow us - // to implement all the required method interfaces. - pb.UnimplementedStateDBServiceServer -} - -// NewStateDBMock is the StateDBMock constructor. -func NewStateDBMock(address string, tvContainer *testvector.Container) *StateDBMock { - return &StateDBMock{ - address: address, - tvContainer: tvContainer, - } -} - -// Start sets up the stateDB server to process requests. -func (server *StateDBMock) Start() { - lis, err := net.Listen("tcp", server.address) - if err != nil { - log.Fatalf("failed to listen: %v", err) - } - - server.srv = grpc.NewServer() - pb.RegisterStateDBServiceServer(server.srv, server) - - log.Infof("StateDB mock server: listening at %s", server.address) - if err := server.srv.Serve(lis); err != nil { - log.Fatalf("failed to serve: %v", err) - } -} - -// Stop stops the server. -func (server *StateDBMock) Stop() { - log.Info("StateDB mock server: stopping...") - server.srv.Stop() -} - -// Set is the mock of the method for setting values in the tree. -func (server *StateDBMock) Set(ctx context.Context, request *pb.SetRequest) (*pb.SetResponse, error) { - keyBIStr, err := getKeyBIStr(request.Key) - if err != nil { - return nil, err - } - - oldRootStr := merkletree.H4ToString([]uint64{request.OldRoot.Fe0, request.OldRoot.Fe1, request.OldRoot.Fe2, request.OldRoot.Fe3}) - log.Debugf("Set called with key %v, value %v, root %v", keyBIStr, request.Value, oldRootStr) - _, newRoot, err := server.tvContainer.FindSMTValue(keyBIStr, oldRootStr) - if err != nil { - return nil, err - } - h4NewRoot, err := merkletree.StringToh4(newRoot) - if err != nil { - return nil, err - } - return &pb.SetResponse{ - NewRoot: &pb.Fea{Fe0: h4NewRoot[0], Fe1: h4NewRoot[1], Fe2: h4NewRoot[2], Fe3: h4NewRoot[3]}, - }, nil -} - -// Get is the mock of the method for getting values from the tree. -func (server *StateDBMock) Get(ctx context.Context, request *pb.GetRequest) (*pb.GetResponse, error) { - keyBIStr, err := getKeyBIStr(request.Key) - if err != nil { - return nil, err - } - - rootStr := merkletree.H4ToString([]uint64{request.Root.Fe0, request.Root.Fe1, request.Root.Fe2, request.Root.Fe3}) - - value, _, err := server.tvContainer.FindSMTValue(keyBIStr, rootStr) - if err != nil { - return nil, err - } - valueBI, ok := new(big.Int).SetString(value, encoding.Base10) - if !ok { - return nil, fmt.Errorf("Could not convert base 10 %q to big.Int", value) - } - valueHex := hex.EncodeBig(valueBI)[2:] - - log.Debugf("Get called with key %v, root %v, returning value %v", keyBIStr, rootStr, valueHex) - return &pb.GetResponse{ - Value: valueHex, - }, nil -} - -// SetProgram is the mock of the method for setting SC contents in the tree. -func (server *StateDBMock) SetProgram(ctx context.Context, request *pb.SetProgramRequest) (*pb.SetProgramResponse, error) { - keyBIStr, err := getKeyBIStr(request.Key) - if err != nil { - return nil, err - } - - _, err = server.tvContainer.FindBytecode(keyBIStr) - if err != nil { - return nil, err - } - return &pb.SetProgramResponse{}, nil -} - -// GetProgram is the mock of the method for getting SC contents from the tree. -func (server *StateDBMock) GetProgram(ctx context.Context, request *pb.GetProgramRequest) (*pb.GetProgramResponse, error) { - keyBIStr, err := getKeyBIStr(request.Key) - if err != nil { - return nil, err - } - - bytecode, err := server.tvContainer.FindBytecode(keyBIStr) - if err != nil { - return nil, err - } - data, err := hex.DecodeHex(bytecode) - if err != nil { - return nil, err - } - return &pb.GetProgramResponse{ - Data: data, - }, nil -} - -func getKeyBIStr(key *pb.Fea) (string, error) { - keyStr := merkletree.H4ToString([]uint64{key.Fe0, key.Fe1, key.Fe2, key.Fe3}) - - if strings.HasPrefix(keyStr, "0x") { // nolint - keyStr = keyStr[2:] - } - - keyBI, ok := new(big.Int).SetString(keyStr, hex.Base) - if !ok { - return "", fmt.Errorf("Could not convert the hex string %q into big.Int", keyStr) - } - keyBytes := merkletree.ScalarToFilledByteSlice(keyBI) - - return new(big.Int).SetBytes(keyBytes).String(), nil -} diff --git a/tools/zkevmprovermock/testvector/main.go b/tools/zkevmprovermock/testvector/main.go deleted file mode 100644 index 8e7bc40316..0000000000 --- a/tools/zkevmprovermock/testvector/main.go +++ /dev/null @@ -1,229 +0,0 @@ -package testvector - -import ( - "encoding/json" - "fmt" - "os" - "strings" - - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/ethereum/go-ethereum/common" - "github.com/spf13/afero" -) - -// E2E contains all the test vectors. -type E2E struct { - Items []*E2EItem -} - -// E2EItem contains an end-to-end test vector. -type E2EItem struct { - BatchL2Data string - GlobalExitRoot string - Traces *Traces - GenesisRaw []*state.GenesisAction -} - -// Traces represents executor processing traces. -type Traces struct { - BatchHash string - OldStateRoot string `json:"old_state_root"` - GlobalHash string - NumBatch uint64 - Timestamp uint64 - SequencerAddr string - - *ProcessBatchResponse -} - -// ProcessBatchResponse contains information about the executor response to a -// ProcessBatch request. -type ProcessBatchResponse struct { - CumulativeGasUsed string `json:"cumulative_gas_used,omitempty"` - Responses []*ProcessTransactionResponse `json:"responses,omitempty"` - NewStateRoot string `json:"new_state_root,omitempty"` - NewLocalExitRoot string `json:"new_local_exit_root,omitempty"` - CntKeccakHashes uint32 `json:"cnt_keccak_hashes,omitempty"` - CntPoseidonHashes uint32 `json:"cnt_poseidon_hashes,omitempty"` - CntPoseidonPaddings uint32 `json:"cnt_poseidon_paddings,omitempty"` - CntMemAligns uint32 `json:"cnt_mem_aligns,omitempty"` - CntArithmetics uint32 `json:"cnt_arithmetics,omitempty"` - CntBinaries uint32 `json:"cnt_binaries,omitempty"` - CntSteps uint32 `json:"cnt_steps,omitempty"` -} - -// ProcessTransactionResponse contains information about the executor response to a -// transaction execution. -type ProcessTransactionResponse struct { - TxHash string `json:"tx_hash"` - Type uint32 - GasLeft string `json:"gas_left"` - GasUsed string `json:"gas_used"` - GasRefunded string `json:"gas_refunded"` - StateRoot string `json:"state_root"` - Logs []*Log - UnprocessedTransaction bool `json:"unprocessed_transaction,omitempty"` - CallTrace *CallTrace `json:"call_trace,omitempty"` -} - -// Log represent logs emitted by LOG opcode. -type Log struct { - Data []string - Topics []string - Address string - BatchNumber uint64 `json:"batch_number"` - TxHash string `json:"tx_hash"` - TxIndex uint32 `json:"tx_index"` - BatchHash string `json:"batch_hash"` - Index uint32 -} - -// CallTrace represents the batch call trace. -type CallTrace struct { - Context *TransactionContext `json:"context,omitempty"` - Steps []*TransactionStep `json:"steps,omitempty"` -} - -// TransactionContext represents a transaction's context. -type TransactionContext struct { - From string `json:"from,omitempty"` - To string `json:"to,omitempty"` - Type string `json:"type,omitempty"` - Data string `json:"data,omitempty"` - Gas string `json:"gas,omitempty"` - Value string `json:"value,omitempty"` - Batch string `json:"batch,omitempty"` - Output string `json:"output,omitempty"` - GasUsed string `json:"gas_used,omitempty"` - ExecutionTime string `json:"execution_time,omitempty"` - OldStateRoot string `json:"old_state_root,omitempty"` - GasPrice string `json:"gasPrice,omitempty"` -} - -// TransactionStep represents a transaction's step. -type TransactionStep struct { - Depth uint32 `json:"depth,omitempty"` - Pc uint64 `json:"pc,omitempty"` - RemainingGas string `json:"remaining_gas,omitempty"` - OpCode string - GasRefund string `json:"gas_refund,omitempty"` - Op string `json:"op,omitempty"` - Error string - StateRoot string `json:"state_root"` - Contract *Contract `json:"contract,omitempty"` - ReturnData []string `json:"return_data,omitempty"` - GasCost string `json:"gas_cost"` - Stack []string - Memory []string -} - -// Contract contains information about SCs executed in a batch. -type Contract struct { - Address string `json:"address,omitempty"` - Caller string `json:"caller,omitempty"` - Value string `json:"value,omitempty"` - Data string `json:"data,omitempty"` - Gas string `json:"gas,omitempty"` -} - -// Container is a wrapper for test vectors. -type Container struct { - E2E *E2E -} - -// NewContainer is the Container constructor. -func NewContainer(testVectorPath string, aferoFs afero.Fs) (*Container, error) { - e2e, err := getE2E(testVectorPath, aferoFs) - if err != nil { - return nil, err - } - - return &Container{ - E2E: e2e, - }, nil -} - -// FindSMTValue searches for the given key on all the genesisRaw items present, -// checking also that the given root was the root returned by the previous item. -// If both the value and the root of the previous item match it returns the -// associated value and new root. -func (c *Container) FindSMTValue(inputKey, oldRoot string) (value, newRoot string, err error) { - zero := common.HexToHash("").String() - var lastValue string - for _, item := range c.E2E.Items { - for index, action := range item.GenesisRaw { - if action.Key == inputKey { - if index > 0 && oldRoot == item.GenesisRaw[index-1].Root || - index == 0 && oldRoot == zero { - return item.GenesisRaw[index].Value, item.GenesisRaw[index].Root, nil - } else { - lastValue = item.GenesisRaw[index].Value - } - } - } - if len(item.GenesisRaw) > 0 && - oldRoot == item.GenesisRaw[len(item.GenesisRaw)-1].Root && - lastValue != "" { - return lastValue, oldRoot, nil - } - } - return "", "", fmt.Errorf("key %q not found for oldRoot %q", inputKey, oldRoot) -} - -// FindBytecode searches for the given key on the value fields of all the -// genesisRaw items present and returns the associated bytecode field on match. -func (c *Container) FindBytecode(inputKey string) (bytecode string, err error) { - for _, item := range c.E2E.Items { - for index, action := range item.GenesisRaw { - if action.Value == inputKey && action.Bytecode != "" { - return item.GenesisRaw[index].Bytecode, nil - } - } - } - return "", fmt.Errorf("bytecode for key %q not found", inputKey) -} - -// FindProcessBatchResponse searches for the responses to a process batch -// request identified by tge batch L2 data. -func (c *Container) FindProcessBatchResponse(batchL2Data string) (*ProcessBatchResponse, error) { - for _, item := range c.E2E.Items { - if strings.Replace(item.BatchL2Data, "0x", "", -1) == strings.Replace(batchL2Data, "0x", "", -1) { - return item.Traces.ProcessBatchResponse, nil - } - } - return nil, fmt.Errorf("ProcessBatchResponse for batchL2Data %q not found", batchL2Data) -} - -func getE2E(testVectorPath string, aferoFs afero.Fs) (*E2E, error) { - e2e := &E2E{} - - err := afero.Walk(aferoFs, testVectorPath, func(wpath string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info == nil || info.IsDir() { - return nil - } - e2eFile, err := getE2EFile(wpath, aferoFs) - if err != nil { - return err - } - e2e.Items = append(e2e.Items, e2eFile.Items...) - - return nil - }) - - return e2e, err -} - -func getE2EFile(filePath string, aferoFs afero.Fs) (*E2E, error) { - contents, err := afero.ReadFile(aferoFs, filePath) - if err != nil { - return nil, err - } - var e2e E2E - if err := json.Unmarshal(contents, &e2e.Items); err != nil { - return nil, err - } - return &e2e, nil -} diff --git a/tools/zkevmprovermock/testvector/testvector_test.go b/tools/zkevmprovermock/testvector/testvector_test.go deleted file mode 100644 index f391049c9e..0000000000 --- a/tools/zkevmprovermock/testvector/testvector_test.go +++ /dev/null @@ -1,859 +0,0 @@ -package testvector_test - -import ( - "fmt" - "path/filepath" - "testing" - - "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/testutils" - "github.com/0xPolygonHermez/zkevm-node/tools/zkevmprovermock/testvector" - "github.com/spf13/afero" - "github.com/stretchr/testify/require" -) - -func TestNewContainer(t *testing.T) { - const defaultSourceDir = "/a/b/c" - - tcs := []struct { - description string - sourceFiles map[string]string - testVectorPath string - expectedContainer *testvector.Container - expectedError bool - expectedErrorMsg string - }{ - { - description: "happy path, single file", - sourceFiles: map[string]string{ - filepath.Join(defaultSourceDir, "a.json"): `[ -{ - "batchL2Data": "0xabc123456", - "globalExitRoot": "0x1234abcd", - "traces": { - "batchHash": "batchHash", - "old_state_root": "old_state_root", - "globalHash": "globalHash", - "numBatch": 1, - "timestamp": 1944498031, - "sequencerAddr": "sequencerAddr", - "responses": [ - { - "tx_hash": "0xabc", - "type": 0, - "gas_left": "28099", - "gas_used": "71901", - "gas_refunded": "0", - "state_root": "0x2031e0233b733481aa0e8c1056b874d68731fc0c673248538f7acfb81d2d7764", - "logs": [ - { - "data": [ - "000000000000000000000002540be400" - ], - "topics": [ - "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "00000000000000000000000000000000", - "4d5cf5032b2a844602278b01199ed191a86c93ff" - ], - "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - "batch_number": 1, - "tx_hash": "0xeeb51664fd2b6dcf865de752589f59f29b8398bdc38b5f556715ae88615c4641", - "tx_index": 0, - "batch_hash": "0x7624c022e923e798a6682171fd27b54912c426cfd92d49fb6be3bf300ba27679", - "index": 0 - } - ], - "unprocessed_transaction": false, - "call_trace": { - "context": { - "from": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", - "to": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - "type": "CALL", - "data": "0x40c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000002540be400", - "gas": "100000", - "value": "0", - "batch": "0x7624c022e923e798a6682171fd27b54912c426cfd92d49fb6be3bf300ba27679", - "output": "", - "gas_used": "71901", - "execution_time": "", - "old_state_root": "0x2031e0233b733481aa0e8c1056b874d68731fc0c673248538f7acfb81d2d7764", - "nonce": 0, - "gasPrice": "1000000000", - "chainId": 1000, - "return_value": [] - }, - "steps": [ - { - "depth": 1, - "pc": 0, - "remaining_gas": "78392", - "opcode": "PUSH1", - "gas_refund": "0", - "op": "0x60", - "error": "", - "state_root": "0xdf403125ab76e36f1fb313619e704e4630b984bd93c3121b3775b71d1b72f9c6", - "contract": { - "address": "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - "caller": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", - "value": "0", - "data": "0x40c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000", - "gas": "100000" - }, - "return_data": [], - "gas_cost": "3", - "stack": [ - "0x80" - ], - "memory": [] - } - ] - } - } - ], - "cumulative_gas_used": "171380", - "new_state_root": "0xb6f5c8f596b7130c7c7eb3257e80badfd7a89aa2977cc6d521a8b97f764230f5", - "new_local_exit_root": "0x00", - "cnt_keccak_hashes": 1, - "cnt_poseidon_hashes": 1, - "cnt_poseidon_paddings": 1, - "cnt_mem_aligns": 1, - "cnt_arithmetics": 1, - "cnt_binaries": 1, - "cnt_steps": 1 - }, - "genesisRaw": [ - { - "address": "addressRaw0", - "type": 0, - "key": "keyRaw0", - "value": "valueRaw0" - }, - { - "address": "addressRaw1", - "type": 1, - "key": "keyRaw1", - "value": "valueRaw1" - }, - { - "address": "addressRaw2", - "type": 2, - "key": "keyRaw2", - "value": "valueRaw2", - "bytecode": "bytecodeRaw2" - }, - { - "address": "addressRaw3", - "type": 3, - "key": "keyRaw3", - "value": "valueRaw3", - "storagePosition": "storagePositionRaw3" - }, - { - "address": "addressRaw4", - "type": 4, - "key": "keyRaw4", - "value": "valueRaw4" - } - ] -} -]`, - }, - testVectorPath: defaultSourceDir, - expectedContainer: &testvector.Container{ - E2E: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - BatchL2Data: "0xabc123456", - GlobalExitRoot: "0x1234abcd", - Traces: &testvector.Traces{ - BatchHash: "batchHash", - OldStateRoot: "old_state_root", - GlobalHash: "globalHash", - NumBatch: 1, - Timestamp: 1944498031, - SequencerAddr: "sequencerAddr", - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - Responses: []*testvector.ProcessTransactionResponse{ - { - TxHash: "0xabc", - Type: 0, - GasLeft: "28099", - GasUsed: "71901", - GasRefunded: "0", - StateRoot: "0x2031e0233b733481aa0e8c1056b874d68731fc0c673248538f7acfb81d2d7764", - Logs: []*testvector.Log{ - { - Data: []string{"000000000000000000000002540be400"}, - Topics: []string{ - "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "00000000000000000000000000000000", - "4d5cf5032b2a844602278b01199ed191a86c93ff", - }, - Address: "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - BatchNumber: 1, - TxHash: "0xeeb51664fd2b6dcf865de752589f59f29b8398bdc38b5f556715ae88615c4641", - TxIndex: 0, - BatchHash: "0x7624c022e923e798a6682171fd27b54912c426cfd92d49fb6be3bf300ba27679", - Index: 0, - }, - }, - UnprocessedTransaction: false, - CallTrace: &testvector.CallTrace{ - Context: &testvector.TransactionContext{ - From: "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", - To: "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - Type: "CALL", - Data: "0x40c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000002540be400", - Gas: "100000", - Value: "0", - Batch: "0x7624c022e923e798a6682171fd27b54912c426cfd92d49fb6be3bf300ba27679", - Output: "", - GasUsed: "71901", - ExecutionTime: "", - OldStateRoot: "0x2031e0233b733481aa0e8c1056b874d68731fc0c673248538f7acfb81d2d7764", - GasPrice: "1000000000", - }, - - Steps: []*testvector.TransactionStep{ - { - Depth: 1, - Pc: 0, - RemainingGas: "78392", - OpCode: "PUSH1", - GasRefund: "0", - Op: "0x60", - StateRoot: "0xdf403125ab76e36f1fb313619e704e4630b984bd93c3121b3775b71d1b72f9c6", - Contract: &testvector.Contract{ - Address: "0x1275fbb540c8efc58b812ba83b0d0b8b9917ae98", - Caller: "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", - Value: "0", - Data: "0x40c10f190000000000000000000000004d5cf5032b2a844602278b01199ed191a86c93ff00000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000", - Gas: "100000", - }, - ReturnData: []string{}, - GasCost: "3", - Stack: []string{"0x80"}, - Memory: []string{}, - }, - }, - }, - }, - }, - CumulativeGasUsed: "171380", - NewStateRoot: "0xb6f5c8f596b7130c7c7eb3257e80badfd7a89aa2977cc6d521a8b97f764230f5", - NewLocalExitRoot: "0x00", - CntKeccakHashes: 1, - CntPoseidonHashes: 1, - CntPoseidonPaddings: 1, - CntMemAligns: 1, - CntArithmetics: 1, - CntBinaries: 1, - CntSteps: 1, - }, - }, - GenesisRaw: []*state.GenesisAction{ - { - Address: "addressRaw0", - Type: 0, - Key: "keyRaw0", - Value: "valueRaw0", - }, - { - Address: "addressRaw1", - Type: 1, - Key: "keyRaw1", - Value: "valueRaw1", - }, - { - Address: "addressRaw2", - Type: 2, - Key: "keyRaw2", - Value: "valueRaw2", - Bytecode: "bytecodeRaw2", - }, - { - Address: "addressRaw3", - Type: 3, - Key: "keyRaw3", - Value: "valueRaw3", - StoragePosition: "storagePositionRaw3", - }, - { - Address: "addressRaw4", - Type: 4, - Key: "keyRaw4", - Value: "valueRaw4", - }, - }, - }, - }, - }, - }, - }, - { - description: "happy path, multiple files", - sourceFiles: map[string]string{ - filepath.Join(defaultSourceDir, "a.json"): `[ -{ - "genesisRaw": [ - { - "address": "addressRaw0", - "type": 0, - "key": "keyRaw0", - "value": "valueRaw0" - } - ] -} -]`, - filepath.Join(defaultSourceDir, "b.json"): `[ -{ - "genesisRaw": [ - { - "address": "addressRaw1", - "type": 1, - "key": "keyRaw1", - "value": "valueRaw1" - } - ] -} -]`, - }, - testVectorPath: defaultSourceDir, - expectedContainer: &testvector.Container{ - E2E: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Address: "addressRaw0", - Type: 0, - Key: "keyRaw0", - Value: "valueRaw0", - }, - }, - }, - { - GenesisRaw: []*state.GenesisAction{ - { - Address: "addressRaw1", - Type: 1, - Key: "keyRaw1", - Value: "valueRaw1", - }, - }, - }, - }, - }, - }, - }, - { - description: "invalid test vector causes error", - sourceFiles: map[string]string{ - filepath.Join(defaultSourceDir, "a.json"): "not a real json", - }, - testVectorPath: defaultSourceDir, - expectedError: true, - expectedErrorMsg: "invalid character 'o' in literal null (expecting 'u')", - }, - { - description: "empty test vector path returns empty object", - sourceFiles: map[string]string{}, - testVectorPath: defaultSourceDir, - expectedError: true, - expectedErrorMsg: fmt.Sprintf("open %s: file does not exist", defaultSourceDir), - }, - } - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - var appFs = afero.NewMemMapFs() - - require.NoError(t, testutils.CreateTestFiles(appFs, tc.sourceFiles)) - - actualContainer, err := testvector.NewContainer(tc.testVectorPath, appFs) - - require.NoError(t, testutils.CheckError(err, tc.expectedError, tc.expectedErrorMsg)) - - if err == nil { - require.Equal(t, tc.expectedContainer.E2E.Items, actualContainer.E2E.Items) - } - }) - } -} - -func TestFindSMTValue(t *testing.T) { - tcs := []struct { - description string - e2e *testvector.E2E - key string - oldRoot string - expectedValue string - expectedNewRoot string - expectedError bool - expectedErrorMsg string - }{ - { - description: "happy path, single item", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - }, - }, - }, - }, - key: "key2", - oldRoot: "root1", - expectedValue: "value2", - expectedNewRoot: "root2", - }, - { - description: "happy path, multiple items", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key3", - Value: "value3", - Root: "root3", - }, - { - Key: "key4", - Value: "value4", - Root: "root4", - }, - }, - }, - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - }, - }, - }, - }, - key: "key2", - oldRoot: "root1", - expectedValue: "value2", - expectedNewRoot: "root2", - }, - { - description: "happy path, first item requires zero root", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - }, - }, - }, - }, - key: "key1", - oldRoot: "0x0000000000000000000000000000000000000000000000000000000000000000", - expectedValue: "value1", - expectedNewRoot: "root1", - }, - { - description: "happy path, querying existing key and last root returns last value of the key", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - { - Key: "key1", - Value: "value3", - Root: "root2", - }, - { - Key: "key4", - Value: "value4", - Root: "root4", - }, - }, - }, - }, - }, - key: "key1", - oldRoot: "root4", - expectedValue: "value3", - expectedNewRoot: "root4", - }, - { - description: "unexisting key gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - }, - }, - }, - }, - key: "key10", - oldRoot: "root1", - expectedError: true, - expectedErrorMsg: `key "key10" not found for oldRoot "root1"`, - }, - { - description: "unmatched root gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Key: "key1", - Value: "value1", - Root: "root1", - }, - { - Key: "key2", - Value: "value2", - Root: "root2", - }, - }, - }, - }, - }, - key: "key1", - oldRoot: "root3", - expectedError: true, - expectedErrorMsg: `key "key1" not found for oldRoot "root3"`, - }, - { - description: "empty GenesisRaw gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - {}, - }, - }, - key: "key1", - oldRoot: "root2", - expectedError: true, - expectedErrorMsg: `key "key1" not found for oldRoot "root2"`, - }, - } - - subject := &testvector.Container{} - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - subject.E2E = tc.e2e - - actualValue, actualRoot, err := subject.FindSMTValue(tc.key, tc.oldRoot) - require.NoError(t, testutils.CheckError(err, tc.expectedError, tc.expectedErrorMsg)) - - if err == nil { - require.Equal(t, tc.expectedValue, actualValue) - require.Equal(t, tc.expectedNewRoot, actualRoot) - } - }) - } -} - -func TestFindBytecode(t *testing.T) { - tcs := []struct { - description string - e2e *testvector.E2E - key string - expectedBytecode string - expectedError bool - expectedErrorMsg string - }{ - { - description: "happy path, single item", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Value: "key1", - Bytecode: "bytecode1", - }, - { - Value: "key2", - Bytecode: "bytecode2", - }, - }, - }, - }, - }, - key: "key2", - expectedBytecode: "bytecode2", - }, - { - description: "happy path, multiple items", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Value: "key3", - Bytecode: "bytecode3", - }, - { - Value: "key4", - Bytecode: "bytecode4", - }, - }, - }, - { - GenesisRaw: []*state.GenesisAction{ - { - Value: "key1", - Bytecode: "bytecode1", - }, - { - Value: "key2", - Bytecode: "bytecode2", - }, - }, - }, - }, - }, - key: "key2", - expectedBytecode: "bytecode2", - }, - { - description: "unexisting key gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Value: "key1", - Bytecode: "bytecode1", - }, - { - Value: "key2", - Bytecode: "bytecode2", - }, - }, - }, - }, - }, - key: "key10", - expectedError: true, - expectedErrorMsg: `bytecode for key "key10" not found`, - }, - { - description: "empty GenesisRaw gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - {}, - }, - }, - key: "key1", - expectedError: true, - expectedErrorMsg: `bytecode for key "key1" not found`, - }, - { - description: "empty bytecode for matching key gives error", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - GenesisRaw: []*state.GenesisAction{ - { - Value: "key1", - }, - }, - }, - }, - }, - key: "key1", - expectedError: true, - expectedErrorMsg: `bytecode for key "key1" not found`, - }, - } - - subject := &testvector.Container{} - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - subject.E2E = tc.e2e - - actualBytecode, err := subject.FindBytecode(tc.key) - require.NoError(t, testutils.CheckError(err, tc.expectedError, tc.expectedErrorMsg)) - - if err == nil { - require.Equal(t, tc.expectedBytecode, actualBytecode) - } - }) - } -} - -func TestFindProcessBatchResponse(t *testing.T) { - tcs := []struct { - description string - e2e *testvector.E2E - batchL2Data string - expectedResponse *testvector.ProcessBatchResponse - expectedError bool - expectedErrorMsg string - }{ - { - description: "happy path, single item", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - BatchL2Data: "0xabc", - Traces: &testvector.Traces{ - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - }, - }, - }, - batchL2Data: "0xabc", - expectedResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - { - description: "happy path, no leading 0x in id", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - BatchL2Data: "0xabc", - Traces: &testvector.Traces{ - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - }, - }, - }, - batchL2Data: "abc", - expectedResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - { - description: "happy path, multiple item", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - BatchL2Data: "0xabc1234", - Traces: &testvector.Traces{ - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "1100", - CntKeccakHashes: 1200, - CntMemAligns: 1300, - }, - }, - }, - { - BatchL2Data: "0xabc", - Traces: &testvector.Traces{ - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - }, - }, - }, - batchL2Data: "0xabc", - expectedResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - { - description: "unhappy path, id not found", - e2e: &testvector.E2E{ - Items: []*testvector.E2EItem{ - { - BatchL2Data: "0xabc", - Traces: &testvector.Traces{ - ProcessBatchResponse: &testvector.ProcessBatchResponse{ - CumulativeGasUsed: "100", - CntKeccakHashes: 200, - CntMemAligns: 300, - }, - }, - }, - }, - }, - batchL2Data: "0x123", - expectedError: true, - expectedErrorMsg: `ProcessBatchResponse for batchL2Data "0x123" not found`, - }, - } - - subject := &testvector.Container{} - - for _, tc := range tcs { - tc := tc - t.Run(tc.description, func(t *testing.T) { - subject.E2E = tc.e2e - - actualResponse, err := subject.FindProcessBatchResponse(tc.batchL2Data) - require.NoError(t, testutils.CheckError(err, tc.expectedError, tc.expectedErrorMsg)) - - if err == nil { - require.Equal(t, tc.expectedResponse, actualResponse) - } - }) - } -} diff --git a/version.go b/version.go new file mode 100644 index 0000000000..2dbd8a0cf5 --- /dev/null +++ b/version.go @@ -0,0 +1,25 @@ +package zkevm + +import ( + "fmt" + "io" + "runtime" +) + +// Populated during build, don't touch! +var ( + Version = "v0.1.0" + GitRev = "undefined" + GitBranch = "undefined" + BuildDate = "Fri, 17 Jun 1988 01:58:00 +0200" +) + +// PrintVersion prints version info into the provided io.Writer. +func PrintVersion(w io.Writer) { + fmt.Fprintf(w, "Version: %s\n", Version) + fmt.Fprintf(w, "Git revision: %s\n", GitRev) + fmt.Fprintf(w, "Git branch: %s\n", GitBranch) + fmt.Fprintf(w, "Go version: %s\n", runtime.Version()) + fmt.Fprintf(w, "Built: %s\n", BuildDate) + fmt.Fprintf(w, "OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH) +} diff --git a/version.mk b/version.mk new file mode 100644 index 0000000000..73db3b019f --- /dev/null +++ b/version.mk @@ -0,0 +1,4 @@ +VERSION := $(shell git describe --tags --always) +GITREV := $(shell git rev-parse --short HEAD) +GITBRANCH := $(shell git rev-parse --abbrev-ref HEAD) +DATE := $(shell LANG=US date +"%a, %d %b %Y %X %z")